I am getting unquoted JSON from a trusted 3rd party that looks like this:
{id: 2, name: Test Testerson, course_progress: 0, last_activity_date: null}, {id: 3, name: Poghos Adamyan, course_progress: 0, last_activity_date: null}
What is the best way using Dart for me to format this into valid JSON for use?
If you're absolutely certain that your response is that verbatim string and that you haven't already decoded it, then you would have to parse it manually and hope that there will never be ambiguity. If the data always follows a strict format and if all fields are always in a specific order, you could write a regular expression to parse it. For example:
void main() {
var s =
'{id: 2, name: Test Testerson, course_progress: 0, last_activity_date: null}, {id: 3, name: Poghos Adamyan, course_progress: 0, last_activity_date: null}';
var re = RegExp(
r'\{'
r'id: (?<id>\d+), '
r'name: (?<name>[^,]+), '
r'course_progress: (?<progress>\d+), '
r'last_activity_date: (?<last>[^}]+)'
r'\}',
);
var matches = re.allMatches(s);
var items = <Map<String, dynamic>>[
for (var match in matches)
<String, dynamic>{
'id': int.parse(match.namedGroup('id')!),
'name': match.namedGroup('name')!,
'course_progress': int.parse(match.namedGroup('progress')!),
'last_activity': DateTime.tryParse(match.namedGroup('last')!),
}
];
items.forEach(print);
}
Related
I am trying to extract a JSON response.When I try to access the object within the json array it returns undefined
weather= [{"id":711,"main":"Smoke","description":"smoke","icon":"50d"}]
var x=JSON.stringify(weather)
x[0].main= returns =>undefined
You can simply use Array#map OR Array#forEach function to get all you JSON data. You do not need to use JSON.stringify in your response.
Demo:
let weather = [{
"id": 711,
"main": "Smoke",
"description": "smoke",
"icon": "50d"
}]
weather.map(function(x) {
console.log(x.id) //711
console.log(x.main) //Smoke
console.log(x.description) //smoke
console.log(x.icon) //50d
})
I'm not sure what you're trying to accomplish or what you've tried, but here is how that works:
const weather = [{"id":711,"main":"Smoke","description":"smoke","icon":"50d"}]
document.querySelector('#id').textContent = weather[0].id
document.querySelector('#json').textContent = JSON.stringify(weather)
ID:
<div id="id"></div>
Stringified JSON:
<div id="json"></div>
To access an element of an array you can reference an index or loop through it:
const myArray = [1, 2, 3];
myArray[0] // 1
myArray[1] // 2
myArray[2] // 3
for (let i = 0 ; i < myArray.length ; i++) {
console.log(myArray[i]);
}
To access a property of an object you can either use dot notation or the key name as the index:
const myObject = {'a': 1, 'b': 2}
myObject.a // 1
myObject['b'] // 2
JSON.stringify converts your JSON into a string. This is useful for sending it over a connection to a host that may or may not recognize JSON.
I have a JSON file with a large amount of the following values:
"values": [
"Foo": 1,
"Bar": 2,
"Baz": 3,
...
],
How do I efficiently convert this into:
"values": [
{
"name": "Foo",
"value": 1
},
{
"name": "Bar",
"value": 2
},
{
"name": "Baz",
"value": 3
},
...
],
Any help would be appreciated!
Okay, so there are two problems with your input. The first is the fact that the given JSON is invalid, so can't directly be parsed. The square brackets after "values" should be curly brackets, to allow for a hash instead of an array:
let raw_old_data =
// Read the old file
fs.readFileSync('./input_data.json').toString()
// Remove all newlines which could interfere with the regex
.replace(/[\r\n]/g, '')
// Replace the square brackets after `"values"` with curly braces
.replace(/"values": \[(.+?)\]/g, '"values": { $1 }');
To convert this (now valid) string to a JSON object, you use JSON.parse:
let old_data = JSON.parse(raw_old_data);
The second problem is that the format in which the values are stored doesn't match your needs. You want to convert from { key: "value" } to [ name: "key", value: "value" ]. The following function can do that, assuming your version of Node supports ES6 (If not, look at Murillo's answer):
function fix_format(obj) {
// This is where we keep the new items in the correct format
let res = [];
// Loop over all values
Object.keys(obj.values).forEach(name => {
let value = obj.values[name];
// Change the format and add to resulting array
res.push({
// If the variable is the same as the key of the hash, it doesn't have to be specified
name,
value,
});
});
return res;
}
All that's then left to do is loop all data from the old object through that function with the Array.map function:
let new_data = old_data.map(fix_format);
And optionally write it back to a file to use with a different program:
fs.writeFileSync('./formatted_data.json', JSON.stringify(data, null, 2));
Note: The 2 in the JSON.stringify function indicates that the resulting JSON should be padded with 2 spaces, to keep it readable.
With ES6:
Object.keys(values).map(name => ({
name,
value: values[name]
}))
Without ES6:
var keys = Object.keys(values);
var newValues = [];
for(var i = 0; i < keys.length; i++){
newValues.push({
name: keys[i],
value: values[keys[i]]
})
}
If your intention is to use the received data i.e obtain data from DB (e.g MSSql, MySql...) using the connection.query(your_custom_sql_query, (err, rows, fields)
for more info:Node.js MySQL Select From Table
I'll recommend you to use:
const myJson = JSON.stringify(rows[0]);
I have a complicated data structure that I need to convert to JSON. The problem is that my field names and values are in an array.
For instance, I have the following (simplified from my code base):
let SampleData = [
{ Field: 'Key', Value: '7'},
{ Field: 'City', Value: 'Some City'},
{ Field: 'Description', Value: 'Some Description'}
];
Basically my data is an array where the first element is the database column name, and the second element is the data in the column. I am trying to get a JSON object that is:
{ Key: 7, City: 'Some City', Description: 'Some Description' }
My real code has the fields and data is structures within the object, so I cannot simply use an Object.create() or Object.assign() as far as I can get working.
I have tried looping through to build a simple string and then use the JSON.parse to break it apart, but this seems like a lot of overhead for something I would have thought would be simpler.
As you asked, here's how to do it:
Mapping the array to an object
Converting the object to JSON
let array = [{
Field: 'Key',
Value: '7'
},
{
Field: 'City',
Value: 'Some City'
},
{
Field: 'Description',
Value: 'Some Description'
}
];
// #1 Mapping the array to an object...
let obj = {};
array.forEach(item => obj[item.Field] = item.Value);
// #2 Converting the object to JSON...
let json = JSON.stringify(obj);
console.log(json);
Bonus (ES6 + reduce):
const obj = array.reduce((acc, { Field, Value }) => ({ ...acc, [Field]: Value }), {});
you can try the below approach . I have used spread operator(ES6) and Object.assign to create the object ,then converted it into json string.
let SampleData = [
{ Field: 'Key', Value: '7'},
{ Field: 'City', Value: 'Some City'},
{ Field: 'Description', Value: 'Some Description'}
];
let obj = Object.assign(...SampleData.map( x => Object.values(x)).map(y => ({[y[0]]: y[1]})));
console.log(obj);
//{ Key: "7", City: "Some City", Description: "Some Description" }
console.log(JSON.stringify(obj));
I had a similar requirement and here is how I achieved it.
var ranges: segmentRange[] = new Array(2);
ranges[0] = { minimumPercentage: 50, maximumPercentage: 60 };
ranges[1] = { minimumPercentage: 30, maximumPercentage: 40 };
const segmentRanges = { segmentRanges: ranges };
return JSON.stringify(segmentRanges);
Output:
{"segmentRanges":[{"minimumPercentage":50,"maximumPercentage":60},{"minimumPercentage":30,"maximumPercentage":40}]}
HTH,
I have a JSON array like this
[
{"id": "someId",
"name": "someName",
"other": "other"},
{"id": "someId1",
"name": "someName1",
"other": "other1"}
]
And i need to iterate over it to retrieve key:value pairs and assign it to object. I need it because i don't need some of the elements and i want some styling.
So, after this manipulation i want to have:
id=someId
name=someName
other=other
id=someId1
name=someName1
other=other1
I will have this after JSON.stringify(created object.)
So for now i have
var data = {};
for(var i = 0; i < docs.length; i++){
data[docs[i]._id] = docs[i]._id;
}
console.log(data);
After this i have
someId = someId
Sorry for mistakes.
The Update !!!!!!!!!!
So the JSON just a sample. The real JSON is returned from mongodb that is why it's valid.
In the for loop i have:
data[docs[i]._id] = docs[i]._id;
and return
someId = someId
but i need
id = someId
So i can't assign key in the loop into object because it takes the value instead.
Thanks.
I am totally unsure what you want exactly, but if you want to iterate over your array of json objects, then you can use jQuery's .each like this:
var arr = [
{'id': 'someId', 'name': 'someName', 'other': 'other'},
{'id': 'someId1', 'name': 'someName1', 'other': 'other1'}
];
$(arr).each(function(index,elem){
console.log(elem.Id);
console.log(elem.name);
console.log(elem.other);
//or watever you want to do with the values
});
moreover: make sure your json objects are valid. In the second json Object, there's a missing double quote from the key name of yours.
In Plain JavaScript you can write something similar as follows
var arr = [
{'id': 'someId', 'name': 'someName', 'other': 'other'},
{'id': 'someId1', 'name': 'someName1', 'other': 'other1'}
];
//plain javascript for in loop
for ( var key in arr){
var nodes = arr[key]
// get to the nested obj
for(var innernodes in nodes){
console.log(innernodes + ' : ' + nodes[innernodes]);
}
}
I'd like to try ServiceStack's json parsing, but I've already figured out how to do something I need via Newtonsoft. Can this same thing by done via ServiceStack?
I've tried with the commented out code but it gives exceptions, see below for exception details.
Thanks!
Josh
[Test]
public void TranslateFromGitHubToCommitMessage()
{
const string json =
#"
{
'commits':
[
{
'author': {
'email': 'dev#null.org',
'name': 'The Null Developer'
},
'message': 'okay i give in'
},
{
'author': {
'email': 'author#github.com',
'name': 'Doc U. Mentation'
},
'message': 'Updating the docs, that\'s my job'
},
{
'author': {
'email': 'author#github.com',
'name': 'Doc U. Mentation'
},
'message': 'Oops, typos'
}
]
}
";
dynamic root = JObject.Parse(json);
//dynamic root = ServiceStack.Text.JsonSerializer.DeserializeFromString<JsonObject>(json);
//dynamic root = ServiceStack.Text.JsonObject.Parse(json);
var summaries = new List<string>();
foreach (var commit in root.commits)
{
var author = commit.author;
var message = commit.message;
summaries.Add(string.Format("{0} <{1}>: {2}", author.name, author.email, message));
}
const string expected1 = "The Null Developer <dev#null.org>: okay i give in";
const string expected2 = "Doc U. Mentation <author#github.com>: Updating the docs, that's my job";
const string expected3 = "Doc U. Mentation <author#github.com>: Oops, typos";
Assert.AreEqual(3, summaries.Count);
Assert.AreEqual(expected1, summaries[0]);
Assert.AreEqual(expected2, summaries[1]);
Assert.AreEqual(expected3, summaries[2]);
}
Exceptions Detail
When using the first commented out line:
dynamic root = ServiceStack.Text.JsonSerializer.DeserializeFromString<JsonObject>(json);
This exception occurs when the method is called.
NullReferenceException:
at ServiceStack.Text.Common.DeserializeListWithElements`2.ParseGenericList(String value, Type createListType, ParseStringDelegate parseFn)
at ServiceStack.Text.Common.DeserializeEnumerable`2.<>c__DisplayClass3.<GetParseFn>b__0(String value)
at ServiceStack.Text.Common.DeserializeSpecializedCollections`2.<>c__DisplayClass7. <GetGenericEnumerableParseFn>b__6(String x)
at ServiceStack.Text.Json.JsonReader`1.Parse(String value)
at ServiceStack.Text.JsonSerializer.DeserializeFromString[T](String value)
at GitHubCommitAttemptTranslator.Tests.GitHubCommitAttemptTranslatorTests.TranslateFromGitHubToCommitMessage()
And, the second:
dynamic root = ServiceStack.Text.JsonObject.Parse(json);
var summaries = new List<string>();
foreach (var commit in root.commits) // <-- Happens here
'ServiceStack.Text.JsonObject' does not contain a definition for 'commits'
Note: the message is 'string' does not contain a definition for 'commits' if I use code from line one, but change the type to or to instead of
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at GitHubCommitAttemptTranslator.Tests.GitHubCommitAttemptTranslatorTests.TranslateFromGitHubToCommitMessage()
After using DynamicJson from .NET 4.0 ServiceStack
Referring to mythz's comment:
This test case works, but if I modify it like below:
var dog = new { Name = "Spot", Parts = new { Part1 = "black", Part2 = "gray" }, Arr = new [] { "one", "two", "three"} };
var json = DynamicJson.Serialize(dog);
var deserialized = DynamicJson.Deserialize(json);
Then, deserialized.Name and Parts are fine, but Arr is of type string.
Also:
If I use ' quotes it doesn't appear to work. Is that normal? json2 works (to the degree that Arr is also still a string), but json3 does not work at all. It just returns
Immediate Window:
deserialized = DynamicJson.Deserialize(json3);
{}
base {System.Dynamic.DynamicObject}: {}
_hash: Count = 1
----- code: -----
var json2 =
#"
{
""Name"": ""Spot"",
""Parts"": {
""Part1"": ""black"",
""Part2"": ""gray""
},
""Arr"": [
""one"",
""two"",
""three""
]
}";
var json3 =
#"
{
'Name': 'Spot',
'Parts': {
'Part1': 'black',
'Part2': 'gray'
},
'Arr': [
'one',
'two',
'three'
]
}";
var deserialized = DynamicJson.Deserialize(json1);
ServiceStack's JSON Serializer also supports dynamic parsing, see examples of how to parse GitHub's JSON in the Dynamic JSON section of the wiki page.