If I had a file whose contents looked like:
{"one": 1}
{"two": 2}
I could simply parse each separate line as a separate JSON object (using JsonCpp). But what if the structure of the file was less convenient like this:
{
"one":1
}
{
"two":2
}
No one has mentioned arrays:
[
{"one": 1},
{"two": 2}
]
Is valid JSON and might do what the OP wants.
Neither example in your question is a valid JSON object; a JSON object may only have one root. You have to split the file into two objects, then parse them.
You can use http://jsonlint.com to see if a given string is valid JSON or not.
So I recommend either changing what ever is dumping multiple JSON objects into a single file to do it in separate files, or to put each object as a value in one JSON root object.
If you don't have control over whatever is creating these, then you're stuck parsing the file yourself to pick out the different root objects.
Here's a valid way of encoding those data in a JSON object:
{
"one": 1,
"two": 2
}
If your really need separate objects, you can do it like this:
{
"one":
{
"number": 1
},
"two":
{
"number": 2
}
}
Rob Kennedy is right. Calling it a second time would extract the next object, and so on.Most of the json lib can not help you to do all in a single root. Unless you are using more high end framework in QT.
You can also use this custom function to parse multiple root elements even if you have complex objects.
static getParsedJson(jsonString) {
const parsedJsonArr = [];
let tempStr = '';
let isObjStartFound = false;
for (let i = 0; i < jsonString.length; i += 1) {
if (isObjStartFound) {
tempStr += jsonString[i];
if (jsonString[i] === '}') {
try {
const obj = JSON.parse(tempStr);
parsedJsonArr.push(obj);
tempStr = '';
isObjStartFound = false;
} catch (err) {
// console.log("not a valid JSON object");
}
}
}
if (!isObjStartFound && jsonString[i] === '{') {
tempStr += jsonString[i];
isObjStartFound = true;
}
}
return parsedJsonArr;
}
Related
I have a json file which looks like this
{
"ActivityId":"CB8FA1DA-DCB4-40B3-9D12-2786BD89B4D4",
"AdditionalParams":{
},
"Extensions":[
{
"Id":"1234",
"IsEnabled":false,
"Name":"Name1"
},
{
"Id":"4567",
"IsEnabled":false,
"Name":"Name2"
},
{
"Id":"8910",
"IsEnabled":true,
"Name":"Name3"
}
]
}
I see a lot of code online which tries to get the IsEnabled,Name fields(as an example). However, I am trying to use rapidjson to print out the array of extensions as is.
Here is the code that I have tried
Document document;
document.Parse(json);
if (document.HasMember(L"Extensions")) {
eventPayload = document[L"Extensions"].GetString();
}
document[L"Extensions"] is not a string, it's an array, so you will have to first getArray, then iterate through it with a JSONIterator and then get the value of IsEnabled.
Also, you don't have to use L"", since they are normal strings and not wide strings.
I have this body request example:
{
"users": [{
"userId": 123
}, {
"userId": 1234
}]
}
For the previous example I receive one std::list<UsersId>* VUsers that have my userId (in this case '123' and '1234'), create cJSON array, iterate my list and get all userId. (Note: the UsersId is one auxiliar class that I use and receive one int in constructor)
cJSON* cJsonUsers = cJSON_CreateArray();
cJSON_AddItemToObject(root, "VUsers", cJsonUsers);
std::list<UsersId>::const_iterator itUsers = VUsers->begin();
while (itUsers != VUsers->end())
{
cJSON *cJsonVNode = cJSON_CreateObject();
cJSON_AddItemToArray(cJsonUsers, cJsonUser);
cJSON_AddNumberToObject(cJsonUser, "userId", itUsers->userId);
++itVNodes;
}
But know I want to the same but make more simple/easy and need to change the body request to something like this:
{
"users": {
"userId": [123, 1234]
}
}
I'm using this c++ library -> https://github.com/DaveGamble/cJSON but I dont understand how to do to implement the modification that I need.
EDIT 2 (PARSE THE JSON)
cJSON* cJsonUsers = cJSON_GetObjectItem(root, "users");
if (!cJsonUsers) return 0;
if (cJsonUsers->type != cJSON_Array) return 0;
std::list<VUserId>* users = new std::list<VUserId>();
cJSON* cJsonVUser;
cJSON_ArrayForEach(cJsonVUser, cJsonUsers)
{
cJSON* cJsonVUserId = cJSON_GetObjectItem(cJsonVUser, "userId");
if (!cJsonVUserId) continue;
int user_id = cJsonVUserId->valueint;
VUserId userId(user_id);
users->push_back(userId);
}
Something like this could work, that is, create the object and array outside of the loop, and insert the numbers inside the loop:
cJSON* cJsonUsers = cJSON_CreateObject();
cJSON_AddItemToObject(root, "users", cJsonUsers);
cJSON* cJsonUserId = cJSON_CreateArray();
cJSON_AddItemToObject(cJsonUsers, "userId", cJsonUserId);
std::list<UsersId>::const_iterator itUsers = VUsers->begin();
while (itUsers != VUsers->end())
{
cJSON_AddItemToArray(cJsonUserId, cJSON_CreateNumber(itUsers->userId));
++itVNodes;
}
Note that there are languages out there that are more convenient to manipulate JSON if you have the flexibility (disclaimer: I was involved in the design of some of these). Of course there are always use cases when you have to use C++ and in which a library makes a lot of sense.
With languages such as C++ or Java, there is an impedance mismatch between objects in the classical sense, and data formats like XML or JSON. For example, with the standardized, declarative and functional XQuery 3.1 this does not need much code to transform the first document into the second:
let $original-document := json-doc("users.json")
return map {
"users" : map {
"userId" : array { $original-document?users?*?userId }
}
}
Hello I am trying to create a list of json objects in groovy
List relClinicStatementList = []
for (BloodTestRow row in BTList){
def jsonListBuilder = new groovy.json.JsonBuilder()
def internalJson = jsonListBuilder{
'targetRelationshipToSource' {
'code' 'part-of'
'codeSystem' 'MG'
}
'observationResult'{
'observationFocus'{
'code' "${row.exam}"
'codeSystem' 'mobiguide'
'displayName' "${row.exam}"
}
'observationValue' {
'physicalQuantity' {
'value' "${row.value}"
'unit' "${row.unit}"
}
}
}
}
println jsonListBuilder.toPrettyString()
relClinicStatementList.add(internalJson)
}
And the toPrettyString() method correctly shows the json structure I want.
However if at the end of the loop I try to print all of the items I have in the list like this:
for (JsonBuilder entry in relClinicStatementList){
println entry.toPrettyString()
}
I get all the elements inside my relClinicalStatement list to be equal to the latest I created... I felt like declaring a new JsonBuilder at each loop would prevent this behaviour... am I missing something? I must admit I come from Java and have the feeling that using groovy classes here makes this behave a little differently from what I expect.
How do I solve this issue?
Thanks in advance
I can't reproduce the behaviour you are seeing, but I think the problem is that I don't believe internalJson is what you think it is (it's a list of 2 closures).
If you change your code to:
List relClinicStatementList = btList.collect { row ->
new groovy.json.JsonBuilder( {
targetRelationshipToSource {
code 'part-of'
codeSystem 'MG'
}
observationResult {
observationFocus {
code "$row.exam"
codeSystem 'mobiguide'
displayName "$row.exam"
}
observationValue {
physicalQuantity {
value "$row.value"
unit "$row.unit"
}
}
}
} )
}
relClinicStatementList.each { entry ->
println entry.toPrettyString()
}
Does it work as you'd expect?
Is there a way to retrieve the set-at-creations properties of an EmberJS object if you don't know all your keys in advance?
Via the inspector I see all the object properties which appear to be stored in the meta-object's values hash, but I can't seem to find any methods to get it back. For example object.getProperties() needs a key list, but I'm trying to create a generic object container that doesn't know what it will contain in advance, but is able to return information about itself.
I haven't used this in production code, so your mileage may vary, but reviewing the Ember source suggests two functions that might be useful to you, or at least worth reviewing the implementation:
Ember.keys: "Returns all of the keys defined on an object or hash. This is useful when inspecting objects for debugging. On browsers that support it, this uses the native Object.keys implementation." Object.keys documentation on MDN
Ember.inspect: "Convenience method to inspect an object. This method will attempt to convert the object into a useful string description." Source on Github
I believe the simple answer is: you don't find a list of props. At least I haven't been able to.
However I noticed that ember props appear to be prefixed __ember, which made me solve it like this:
for (f in App.model) {
if (App.model.hasOwnProperty(f) && f.indexOf('__ember') < 0) {
console.log(f);
}
};
And it seems to work. But I don't know whether it's 100% certain to not get any bad props.
EDIT: Adam's gist is provided from comments. https://gist.github.com/1817543
var getOwnProperties = function(model){
var props = {};
for(var prop in model){
if( model.hasOwnProperty(prop)
&& prop.indexOf('__ember') < 0
&& prop.indexOf('_super') < 0
&& Ember.typeOf(model.get(prop)) !== 'function'
){
props[prop] = model[prop];
}
}
return props;
}
Neither of these answers are reliable, unfortunately, because any keys paired with a null or undefined value will not be visible.
e.g.
MyClass = Ember.Object.extend({
name: null,
age: null,
weight: null,
height: null
});
test = MyClass.create({name: 'wmarbut'});
console.log( Ember.keys(test) );
Is only going to give you
["_super", "name"]
The solution that I came up with is:
/**
* Method to get keys out of an object into an array
* #param object obj_proto The dumb javascript object to extract keys from
* #return array an array of keys
*/
function key_array(obj_proto) {
keys = [];
for (var key in obj_proto) {
keys.push(key);
}
return keys;
}
/*
* Put the structure of the object that you want into a dumb JavaScript object
* instead of directly into an Ember.Object
*/
MyClassPrototype = {
name: null,
age: null,
weight: null,
height: null
}
/*
* Extend the Ember.Object using your dumb javascript object
*/
MyClass = Ember.Object.extend(MyClassPrototype);
/*
* Set a hidden field for the keys the object possesses
*/
MyClass.reopen({__keys: key_array(MyClassPrototype)});
Using this method, you can now access the __keys field and know which keys to iterate over. This does not, however, solve the problem of objects where the structure isn't known before hand.
I use this:
Ember.keys(Ember.meta(App.YOUR_MODEL.proto()).descs)
None of those answers worked with me. I already had a solution for Ember Data, I was just after one for Ember.Object. I found the following to work just fine. (Remove Ember.getProperties if you only want the keys, not a hash with key/value.
getPojoProperties = function (pojo) {
return Ember.getProperties(pojo, Object.keys(pojo));
},
getProxiedProperties = function (proxyObject) {
// Three levels, first the content, then the prototype, then the properties of the instance itself
var contentProperties = getPojoProperties(proxyObject.get('content')),
prototypeProperties = Ember.getProperties(proxyObject, Object.keys(proxyObject.constructor.prototype)),
objectProperties = getPojoProperties(proxyObject);
return Ember.merge(Ember.merge(contentProperties, prototypeProperties), objectProperties);
},
getEmberObjectProperties = function (emberObject) {
var prototypeProperties = Ember.getProperties(emberObject, Object.keys(emberObject.constructor.prototype)),
objectProperties = getPojoProperties(emberObject);
return Ember.merge(prototypeProperties, objectProperties);
},
getEmberDataProperties = function (emberDataObject) {
var attributes = Ember.get(emberDataObject.constructor, 'attributes'),
keys = Ember.get(attributes, 'keys.list');
return Ember.getProperties(emberDataObject, keys);
},
getProperties = function (object) {
if (object instanceof DS.Model) {
return getEmberDataProperties(object);
} else if (object instanceof Ember.ObjectProxy) {
return getProxiedProperties(object);
} else if (object instanceof Ember.Object) {
return getEmberObjectProperties(object);
} else {
return getPojoProperties(object);
}
};
In my case Ember.keys(someObject) worked, without doing someObject.toJSON().
I'm trying to do something similar, i.e. render a generic table of rows of model data to show columns for each attribute of a given model type, but let the model describe its own fields.
If you're using Ember Data, then this may help:
http://emberjs.com/api/data/classes/DS.Model.html#method_eachAttribute
You can iterate the attributes of the model type and get meta data associated with each attribute.
This worked for me (from an ArrayController):
fields: function() {
var doc = this.get('arrangedContent');
var fields = [];
var content = doc.content;
content.forEach(function(attr, value) {
var data = Ember.keys(attr._data);
data.forEach(function(v) {
if( typeof v === 'string' && $.inArray(v, fields) == -1) {
fields.push(v);
}
});
});
return fields;
}.property('arrangedContent')
I have some documents saved in a collection (called urls) that look like this:
{
payload:{
url_google.com:{
url:'google.com',
text:'search'
}
}
},
{
payload:{
url_t.co:{
url:'t.co',
text:'url shortener'
}
}
},
{
payload:{
url_facebook.com:{
url:'facebook.com',
text:'social network'
}
}
}
Using the mongo CLI, is it possible to look for subdocuments of payload that match /^url_/? And, if that's possible, would it also be possible to query on the match's subdocuments (for example, make sure text exists)?
I was thinking something like this:
db.urls.find({"payload":{"$regex":/^url_/}}).count();
But that's returning 0 results.
Any help or suggestions would be great.
Thanks,
Matt
It's not possible to query against document keys in this way. You can search for exact matches using $exists, but you cannot find key names that match a pattern.
I assume (perhaps incorrectly) that you're trying to find documents which have a URL sub-document, and that not all documents will have this? Why not push that type information down a level, something like:
{
payload: {
type: "url",
url: "Facebook.com",
...
}
}
Then you could query like:
db.foo.find({"payload.type": "url", ...})
I would also be remiss if I did not note that you shouldn't use dots (.) is key names in MongoDB. In some cases it's possible to create documents like this, but it will cause great confusions as you attempt to query into embedded documents (where Mongo uses dot as a "path separator" so to speak).
You can do it but you need to use aggregation: Aggregation is pipeline where each stage is applied to each document. You have a wide range of stages to perform various tasks.
I wrote an aggregate pipeline for this specific problem. If you don't need the count but the documents itself you might want to have a look at the $replaceRoot stage.
EDIT: This works only from Mongo v3.4.4 onwards (thanks for the hint #hwase0ng)
db.getCollection('urls').aggregate([
{
// creating a nested array with keys and values
// of the payload subdocument.
// all other fields of the original document
// are removed and only the filed arrayofkeyvalue persists
"$project": {
"arrayofkeyvalue": {
"$objectToArray": "$$ROOT.payload"
}
}
},
{
"$project": {
// extract only the keys of the array
"urlKeys": "$arrayofkeyvalue.k"
}
},
{
// merge all documents
"$group": {
// _id is mandatory and can be set
// in our case to any value
"_id": 1,
// create one big (unfortunately double
// nested) array with the keys
"urls": {
"$push": "$urlKeys"
}
}
},
{
// "explode" the array and create
// one document for each entry
"$unwind": "$urls"
},
{
// "explode" again as the arry
// is nested twice ...
"$unwind": "$urls"
},
{
// now "query" the documents
// with your regex
"$match": {
"urls": {
"$regex": /url_/
}
}
},
{
// finally count the number of
// matched documents
"$count": "count"
}
])