JSON array with multiple values c++ - c++

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 }
}
}

Related

How to return json string of arrays using rapidjson

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.

How to return an JSON object I made in a reduce function

I need your help about CouchDB reduce function.
I have some docs like:
{'about':'1', 'foo':'a1','bar':'qwe'}
{'about':'1', 'foo':'a1','bar':'rty'}
{'about':'1', 'foo':'a2','bar':'uio'}
{'about':'1', 'foo':'a1','bar':'iop'}
{'about':'2', 'foo':'b1','bar':'qsd'}
{'about':'2', 'foo':'b1','bar':'fgh'}
{'about':'3', 'foo':'c1','bar':'wxc'}
{'about':'3', 'foo':'c2','bar':'vbn'}
As you can seen they all have the same key, just the values are differents.
My purpse is to use a Map/Reduce and my return expectation would be:
'rows':[ 'keys':'1','value':{'1':{'foo':'a1', 'at':'rty'},
'2':{'foo':'a2', 'at':'uio'},
'3':{'foo':'a1', 'at':'iop'}}
'keys':'1','value':{'foo':'a1', 'bar','rty'}
...
'keys':'3','value':{'foo':'c2', 'bar',vbn'}
]
Here is the result of my Map function:
'rows':[ 'keys':'1','value':{'foo':'a1', 'bar','qwe'}
'keys':'1','value':{'foo':'a1', 'bar','rty'}
...
'keys':'3','value':{'foo':'c2', 'bar',vbn'}
]
But my Reduce function isn't working:
function(keys,values,rereduce){
var res= {};
var lastCheck = values[0];
for(i=0; i<values.length;++i)
{
value = values[i];
if (lastCheck.foo != value.foo)
{
res.append({'change':[i:lastCheck]});
}
lastCheck = value;
}
return res;
}
Is it possible to have what I expect or I need to use an other way ?
You should not do this in the reduce function. As the couchdb wiki explains:-
If you are building a composite return structure in your reduce, or only transforming the values field, rather than summarizing it, you might be misusing this feature.
There are two approaches that you can take instead
Transform the results at your application layer.
Use the list function.
Lists functions are simple. I will try to explain them here:
Lists like views are saved in design documents under the key lists. Like so:
"lists":{
"formatResults" : "function(head,req) {....}"
}
To call the list function you use a url like this
http://localhost:5984/your-database/_design/your-designdoc/_list/your-list-function/your-view-name
Here is an example of list function
function(head, req) {
var row = getRow();
if (!row){
return 'no ingredients'
}
var jsonOb = {};
while(row=getRow()){
//construct the json object here
}
return {"body":jsonOb,"headers":{"Content-Type" : "application/json"}};
}
The getRow function is of interest to us. It contains the result of the view. So we can query it like
row.key for key
row.value for value
All you have to do now is construct the json like you want and then send it.
By the way you can use log
to debug your functions.
I hope this helps a little.
Apparently now you need to use
provides('json', function() { ... });
As in:
Simplify Couchdb JSON response

How to read a JSON file containing multiple root elements?

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;
}

Reflection on EmberJS objects? How to find a list of property keys without knowing the keys in advance

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')

Mongodb - regex match of keys for subdocuments

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"
}
])