JSONPatch WCF REST API getting invalid payload error - swap

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.

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"));

controller misinterprets input?

I have this controller
public async Task<ActionResult> SubmitFormAsync([FromBody] Dictionary<string, string> input, Guid formGuid)
for which I via postman provide the input
{
"input": {
"firstname": "Toren",
"jobtitle": "Activist",
"lastname": "SO",
"message": "",
"phone": "+123455667"
}
}
but I keep getting this error in postman
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-79f401cda7f4cdb640dbd8c95dc851d5-a6b4228c3e1675ba-00",
"errors": {
"input": [
"The input field is required."
],
"$.input": [
"The JSON value could not be converted to System.Collections.Generic.Dictionary`2[System.String,System.String]. Path: $.input | LineNumber: 1 | BytePositionInLine: 12."
]
}
}
I know it means that my input is wrong, but why is it wrong I cannot figure out.
You need to post the body, without key as below --
{
"firstname": "Toren",
"jobtitle": "Activist",
"lastname": "SO",
"message": "",
"phone": "+123455667"
}
and pass the guid in query string.

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();

QJsonDocument::array() and QJsonDocument::object()

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

JSONAPI - Difference between self and related in a links resource

Why is the self and related references different in the below JSONAPI resource? Aren't they pointing to the same resource? What is the difference between going to /articles/1/relationships/tags and /articles/1/tags?
{
"links": {
"self": "/articles/1/relationships/tags",
"related": "/articles/1/tags"
},
"data": [
{ "type": "tags", "id": "2" },
{ "type": "tags", "id": "3" }
]
}
You can read about that here: https://github.com/json-api/json-api/issues/508.
Basically, with /articles/1/relationships/tags response will be object which represents relationship between articles and tags. The response could be something like this (what you put in your question):
{
"links": {
"self": "/articles/1/relationships/tags",
"related": "/articles/1/tags"
},
"data": [
{ "type": "tags", "id": "2" },
{ "type": "tags", "id": "3" }
]
}
This response gives only the necessary data (in primary data attribute - data) to manipulate the relationship and not resources connected with relationship. That being said, you'll call /articles/1/relationships/tags if you want to create new relationship, add a new tag (basically updating relationship) to article, read which tags belong to article (you only need identity to search them on server) or delete article tags.
On the other hand, calling /articles/1/tags will respond with tags as primary data with all the other properties that they have (articles, relationships, links, and other top-level attributes such include, emphasized text, links and/or jsonapi).
They are different. Here is an example from my project.
Try Get http://localhost:3000/phone-numbers/1/relationships/contact you will get response like this:
{
"links": {
"self": "http://localhost:3000/phone-numbers/1/relationships/contact",
"related": "http://localhost:3000/phone-numbers/1/contact"
},
"data": {
"type": "contacts",
"id": "1"
}
}
You didn't get the attributes and relationships which is probably you want to retrieve.
Then
Try Get http://localhost:3000/phone-numbers/1/contact you will get response like this:
{
"data": {
"id": "1",
"type": "contacts",
"links": {
"self": "http://localhost:3000/contacts/1"
},
"attributes": {
"name-first": "John",
"name-last": "Doe",
"email": "john.doe#boring.test",
"twitter": null
},
"relationships": {
"phone-numbers": {
"links": {
"self": "http://localhost:3000/contacts/1/relationships/phone-numbers",
"related": "http://localhost:3000/contacts/1/phone-numbers"
}
}
}
}
}
You can see you retrieved all the information you want, including the attributes and relationships.
But you should know that relationships can be used for some purpose. Please read http://jsonapi.org/format/#crud-updating-to-one-relationships as a sample.

Resources