QJsonDocument::array() and QJsonDocument::object() - qt

I am reading the QJsonDocument documentation and I use QJsonDocument with following line:
emit this->ueSignalNewDataArrivedPlaces(QJsonDocument::fromBinaryData(incomingData[0].toByteArray()));
and I do not understand, after this line, should I use QJsonDocument::array() or QJsonDocument::object(), i.e., in what situations does QJsonDocument create array and in what situations does create object?

A JSON array is an ordered list, it is written as:
[ <item1>, <item2>, <item3> ]
while a JSON object is a named list, written as:
{
<name1>: <item1>,
<name2>: <item2>
}
In Qt, a QJsonArray is equivalent to a QVariantList (QList<QVariant>) and a QJsonObject is equivalent to QVariantMap (QMap<QString, QVariant>).
Which one you have to use depends on the file you are parsing.
For instance, taking Wikipedia example:
{
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
},
{
"type": "mobile",
"number": "123 456-7890"
}
],
"children": [],
"spouse": null
}
You would use a QJsonArray to get the list of phoneNumbers, each element of phoneNumbers is a QJsonObject whith 2 named values: type and number.
If in your code you need to manipulate a JSON element but you do not know its type you can use QJsonValue, which is one of: QJsonObject, QJsonArray, bool, double or a QString

Related

Using JSONPath to filter and get only specific properties as result?

Is it possible to use JSONPath to both filter and "select" properties to keep for the result.
For instance if we have the following JSON:
{
"firstName": "John",
"lastName": "doe",
"age": 26,
"address": {
"streetAddress": "naist street",
"city": "Nara",
"postalCode": "630-0192"
},
"phoneNumbers": [
{
"type": "iPhone",
"number": "0123-4567-8888"
},
{
"type": "home",
"number": "0123-4567-8910"
}
]
}
And we run a JSONPath like:
$.phoneNumbers[?(#.type=='iPhone')]
We would end up with the result:
[
{
"type": "iPhone",
"number": "0123-4567-8888"
}
]
Now lets say that what I actually want is the phonenumber.. so we could do this:
$.phoneNumbers[?(#.type=='iPhone')].number
Which would result in:
[
"0123-4567-8888"
]
However.. the result that I would like to get would be:
[
{
"number": "0123-4567-8888"
}
]
Notice how the actual JSON-object is returned and the property..
Is that possible to achive somehow using JSONPath?
Since you know what property you're looking for (i.e. number), what you can do is to construct a new Json object with the property name and the returned value.
The actual implementation depends on what programming language you're using, but the pseudocode should look somewhat like this:
returnedList = json.find("$.phoneNumbers[?(#.type=='iPhone')].number")
initialize newJsonArray
foreach(returnedValue in returnedList):
newJsonArray.add(newJsonObject("number", returnedValue))
An alternative way to tackle the problem in OOP languages is to use lambda functions to filter your Json objects instead of using Jsonpath filters. An example on how to do it in C# using Newtonsoft.Json:
JArray jArray = new JArray(jObject.SelectToken("$.phoneNumbers").Where(x => x["type"].ToString() == "iPhone"));

How to get the first value of a filtered JSONPath output

Below is the sample json that I used to get data based on string search using JSONPath.
{
"tool":
{
"jsonpath":
{
"creator":
{
"name": "Jayway Inc.",
"location":
[
"Malmo",
"San Francisco",
"Helsingborg"
]
}
}
},
"book":
[
{
"title": "Beginning JSON",
"price": 49.99
},
{
"title": "JSON at Work",
"price": 59.99
}
]
}
The JSONPath expression used is
"$.book[?(#.price == 49.99)].title"
The response for the above JSONPath is an array with single string that is the title.
[
"Beginning JSON"
]
Is it possible to get the output as a String instead of an array. It is ok to get the first value if it contains multiple values in the array.

Recursion closure in groovy json [duplicate]

This question already has answers here:
Groovy :: Map Find Recursive
(1 answer)
Recursively extracting JSON field values in Groovy
(1 answer)
Closed 5 years ago.
I am trying to fetch all the values from a json whose key name is "label" and want to store in a list.
My problem is, the position of label key is not fixed.Sometimes it comes under parent node sometimes in child and sometime under child to child.We can use recursive closure in groovy but i don't know how?
Json::
[
{
{
"id": "2",
"label": "NameWhatever"
},
{
"id": "123",
"name": "Some Parent Element",
"children": [{
"id": "123123",
"label": "NameWhatever"
},
{
"id": "123123123",
"name": "Element with Additional Children",
"children": [{
"id": "123123123",
"label": "WhateverChildName"
},
{
"id": "12112",
"name": "Element with Additional Children",
"children": [{
"id": "123123123",
"label": "WhateverChildName"
},
{
"id": "12112",
"name": "Element with Additional Children",
"children": [{
"id": "12318123",
"label": "WhateverChildName"
},
{
"id": "12112",
"label": "NameToMap"
}
]
}
]
}
]
}
]
}
]
Based on similar question
import groovy.json.JsonSlurper
def mapOrCollection (def it) {
it instanceof Map || it instanceof Collection
}
def findDeep(def tree, String key, def collector) {
switch (tree) {
case Map: return tree.each { k, v ->
mapOrCollection(v)
? findDeep(v, key, collector)
: k == key
? collector.add(v)
: null
}
case Collection: return tree.each { e ->
mapOrCollection(e)
? findDeep(e, key, collector)
: null
}
default: return null
}
}
def collector = []
def found = findDeep(new JsonSlurper().parseText(json), 'label', collector)
println collector
Assuming variable json contains the given json input from question, prints:
[NameWhatever, NameWhatever, WhateverChildName, WhateverChildName, WhateverChildName, NameToMap]

JSONPatch WCF REST API getting invalid payload error

I am trying to use JSONPatch(KevinDockx version) in my WCF REST API(ASP.NET v4.5). My operation contract is as below:-
[OperationContract]
[WebInvoke(UriTemplate = "/{raceId}/participants", Method = "PATCH")]
void UpdateRace(string id, JsonPatchDocument<ParticipantContract[]> participantsContract);
And implementation as follows :-
public void UpdateRace(string id, JsonPatchDocument<ParticipantContract[]> participantsContract)
{
//Someoperation
}
My data is like the below format where I want to perform add, update delete, move and swap operations on the participants array.
{
"raceId" : 1
"participants": [
{
"id": "abc",
"car": "Mercedes",
"model": "F1 W08 EQ Power",
"teamname": "Mercedes-AMG Petronas Motorsport",
"driver": {
"id": "111",
"firstname": "Lewis",
"lastname": "Hamilton",
"age": "29"
},
"codriver": {
"id": "222",
"firstname": "Valtteri",
"lastname": "Bottas",
"age": "32"
}
},
{
"id": "def",
"car": "Ferrari",
"model": "SF70H",
"teamname": "Scuderia Ferrari",
"borrower": {
"id": "333",
"firstname": "Sebastian",
"lastname": "Vettel",
"age": "30"
},
"coborrower": {
"id": "444",
"firstname": "Kimi",
"lastname": "Räikkönen",
"age": "37"
}
}
]
}
On JSON deserialization I am getting below error:-
{
"summary": "Bad Request",
"details": "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ParticipantContract' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\nPath '', line 1, position 1."
}
Can you help me with what I am missing in this? Is there something additional that needs to be done?
As I can see your JSON object is not valid
{
"raceId" : 1 // you missed comma here
"participants": [
{
Just checking for any other mistake in your JSON object and passing a valid JSON will fix the error.

How can I Extract a Large json Array in U-SQL and Include meta-data?

I am trying to extract a large amount of Data from a json document. There are about 1500 nodes per json document. When I attempt to load the body node I get the 128KB limit error. I have found a way to load the node but I have to go all the way down to the array list. JsonExtractor("body.nprobe.items[*]"); The issue I am having is that I cannot access any other part of the json document, I need to get the meta data, like: Id, SerialNumber etc. Should the json file be changed in some way? The data I need is 3 levels down. The json has be obfuscated and shortened, the real file is about 33K lines of formatted json about 1500 items with n-20 fields in each.
{
"headers": {
"pin": "12345",
"Type": "URJ201W-GNZGK",
"RTicks": "3345",
"SD": "211",
"Jov": "juju",
"Market": "Dal",
"Drst": "derre",
"Model": "qw22",
"DNum": "de34",
"API": "34f",
"Id": "821402444150002501"
},
"Id": "db5aacae3778",
"ModelType": "URJ",
"body": {
"uHeader": {
"ID": "821402444150002501",
"SerialNo": "ee028861",
"ServerName": "BRXTTY123"
},
"header": {
"form": 4,
"app": 0,
"Flg": 1,
"Version": 11056,
"uploadID": 1,
"uDate": "2016-04-14T18:29"
},
"nprobe": {
"items": [{
"purchaseDate": "2016-04-14T18:21:09",
"storeLoc": {
"latitude": 135.052335,
"longitude": 77.167005
},
"sr": {
"ticks": 3822,
"SkuId": "24",
"Data": {
"X": "0.00068",
"Y": "0.07246",
}
}
},
{
"purchaseDate": "2016-04-14T18:21:09",
"storeLoc": {
"latitude": 135.052335,
"longitude": 77.167005
},
"sr": {
"ticks": 3823,
"SkuId": "25",
"Data": {
"X": "0",
"Y": "2",
}
}
}]
}
},
"Messages": []
}
Thanks.
You'll have to use CROSS APPLY:
https://msdn.microsoft.com/en-us/library/azure/mt621307.aspx
and EXPLODE:
https://msdn.microsoft.com/en-us/library/azure/mt621306.aspx
See a worked out solution here:
https://github.com/algattik/USQLHackathon/blob/master/VS-Solution/USQLApplication/ciam-to-sqldw.usql
https://github.com/algattik/USQLHackathon/blob/master/Samples/Customer/customers%202016-08-10.json
-- IMPROVED ANSWER: --
As this solution will not work for you since your inner JSON is too large to fit in a string, you can parse the input twice:
DECLARE #input string = #"/so.json";
REFERENCE ASSEMBLY [Newtonsoft.Json];
REFERENCE ASSEMBLY [Microsoft.Analytics.Samples.Formats];
#meta =
EXTRACT Id string
FROM #input
USING new Microsoft.Analytics.Samples.Formats.Json.JsonExtractor();
#items =
EXTRACT purchaseDate string
FROM #input
USING new Microsoft.Analytics.Samples.Formats.Json.JsonExtractor("body.nprobe.items[*]");
#itemsFull =
SELECT Id,
purchaseDate
FROM #meta
CROSS JOIN #items;
OUTPUT #itemsFull
TO "/items_full.csv"
USING Outputters.Csv();

Resources