I am using Json Patch library to perfrom a Patch operation using REST. Now I have the follwoing json document:
{
"id":1,
"ref":{"r1":1,"r2":2}, // header level
"child":[
{
"childId":1,
"ref":{"cc1":1,"cc2":2} // line level
},
{
"childId":2,
"ref":{"cc3":2} // line level
}
]
}
Now As per Json Patch doc we at the header level we can update the ref r1 using the following path /ref/r1 .
Now I am trying to perform operation on the line level child ref. Since child is an array I can use the path /child/0/ref/cc1. But as can be seen from the path I have to specify the index also which is 0 in the previous case.
Now for API consumers asking them to give the index of the array become difficult. So is there any way to customize json patch so that we can bypass the index requirement or what are the other ways to handle this scenario?
I'm not an expert in JSON-Patch, i've just read about it.
from what i understood, is the most important part is to let the API consumers access to your JSON without giving them index,
I think hashmap would help in this case, by getting the index of each element and generate a specific ID for it, then you can save them in the hashmap list, each index has its own ID.
a sample:
HashMap<String, String> elementIndex = new HashMap<[UUID], [elementIndex]>();
you can choose whatever DataType you want, not necessary String
In this case it doesn't matter which index number, it is all about the fixed UUID.
So the path will be in this case /child/{UUID}/ref/cc1 also when you receive the path you can access the UUID and replace it with its elementIndex, now you have the correct path which is /child/0/ref/cc1
and if you want to know how to pass a dynamic value to a JSON Object, there are multiple ways to do it,
this question will help:
How to pass dynamic value to a JSON String, -Convert the JSONObject to String before-
NOTE: It is not necessary to replace it with index, you can do it the way you like could be.
And i believe there are better answers if someone knows more about JSON-patch.
i hope that was helpful, or at least gives you an idea about how to solve it.
Related
I have a question about key-value pairs in a JSON array. Let's say I want to create a dynamic code that can be used across multiple responses where I want to pick out the first JSON array, how do I go about doing that? Currently, the code below looks for a JSON array known as 'test', but the issue here is that I can only use this code for an endpoint to spits out a JSON array that has the DTD 'test'.
What I was hoping is change the line of code below so that instead of 'test' it will be 0 or first or something like that.
httpResponse.getBody()
.getObject()
.getJSONArray("test")
.getJSONObject(0)
.get("value")
.toString();
Well, it's actually unusual to do that. Because the first item you put into a JSON object is not the first object you retrieve, JSON library puts it in an alphabetic order.
Either way, you can use the static method of JsonObject getNames() and get field names and then retrieve the first name.
EDIT:
Here is an example:
System.out.println(new JSONObject().put("second", "goes second").put("first","goes first").toString());
output:
{"first":"goes first","second":"goes second"}
And the static JSONObject.getNames():
for(String str:JSONObject.getNames(jsOb))
{
System.out.println("key="+str +", value="+jsOb.getString(str));
}
output:
key=first, value=goes first
key=second, value=goes second
There are 2 json, there multiple paths which is needed to be applied on both json. Then these jsons should be compared via some assert in test. The ide solution whould be:
Stirng actualJson - ....
Stirng expectedJson - ....
Stirng actualJsonFiltered - filter(actualJson, lisofJsonPath);
Stirng expectedJsonFiltered - filter(expectedJson, lisofJsonPath);
JSONAssert.assertEquals(actualJsonFiltered, expectedJsonFiltered);
What is not a solutiom:
1. Any code like that:
for(String p: lisofJsonPath) {
assertEquals(JsonPath.read(actualJson, p), JsonPath.read(expectedJson , p);
}
It is needed to filter jsons and show/fail with all existing path. Show error that several paths are not matches. Not one by one json path matching.
org.assertj.core.api.SoftAssertions - also is not a solution because it is hard to understand from message what assetons are failed.
harcrest allOf/anyOf also is not a solution because it fails on first matched asseretion not combinig them.
P.S. Any suggestions for json diff visualizations are wellcome. The ideal way looks like this. (but this is in javascript)
First,
accept the following:
JSON is an unordered collection of key-value pairs.
It is hard to compare an unordered collection of anything.
If you order the key-value pairs (sorted by key) and you represent the JSON value as a String (for example: "{\"keyA\":\"blam\",\"keyB\":\"kapow\"}") you can compare the JSON values using a string comparison.
I will call the sorted form of JSON "cannonical JSON form".
Once you accept the above as true and/or real,
this becomes the solution to your problem:
Create a tool (perhaps a single class) that accepts JSON and outputs the cannonical JSON form (this is the non-trivial portion of this solution):
Get the canonical JSON form for both of your JSON values.
Compare the cannonical JSON forms using assertEquals.
I am using proto 3 (java) in my projects . I have some huge protobufs embedded with smaller messages . Is there a way I can acheive partial decoding of only few nested sub messages that I want to look at. The current issue I am having is I need to join this huge proto based record data with another records ,but my join are based on very small sub messages ,so I don't want to decode the entire huge protobuf and be able to only decode the nested message (string id) to join and then only decode the entire protobuf for the joined data.
I tried using the [lazy=true] tagging method , but I don't see any difference in generated code , also I tried benchmarking the deserialization time with and without the lazy key work and it didn't seem to affect at all . Is this feature by default on for all fields? Or is this even possible? I do see there are few classes LazyFields.java and test cases in the protobuf-github so I assume this feature has been implemented.
For those that happen to look at this conversation later and finding it hard to understand, here's what Marc's talking about:
If your object is something like
message MyBigMessage{
string id = 1;
int sourceType = 2 ;
And many other fields here, that would be expensive to parse .......
}
And you get a block of bytes that you have to parse. But you want to only parse messages from a certain source and maybe match a certain id range.
You could first parse those bytes with another message as:
message MyFilterMessage{
string id = 1; //has to be 1 to match
int sourceType = 2 ; //has to be 1 to match
And NOTHING ELSE here.......
}
And then, you could look at sourceType and id. If they match whatever you are filtering for, then, you could go and parse the bytes again, but this time, using MyBigMessage to parse the whole thing.
One other thing to know:
FYI: As of 2017, lazy parsing was disabled in Java (except MessageSet) according to this post:
https://github.com/protocolbuffers/protobuf/issues/3601#issuecomment-341516826
I dont know the current status. Too lazy to try to find out ! :-)
I have a very simple question...
In my Android app i'm forming a JSON string to send to my server... there are no error in my code, but Java (or Android) puts the values in a different order of mine and I don't know why...
I want to solve this issue, because I need to process that JSON string in the server to update some tables of my database... my PHP code in the server uses the same order I used in my app to decode the JSON string, but because of Android (or Java) that changes the order, I'm having troubles to update the tables...
Any ideas? Thanks in advance!
I'm talking about this:
In my app:
json_data.put("id_visit", visits.getString(visits.getColumnIndexOrThrow("id_visit")));
json_data.put("id_form", visits.getString(visits.getColumnIndexOrThrow("id_form")));
json_data.put("id_establishment", visits.getString(visits.getColumnIndexOrThrow("id_establishment")));
json_data.put("id_promoter", visits.getString(visits.getColumnIndexOrThrow("id_promoter")));
json_data.put("actual_date", visits.getString(visits.getColumnIndexOrThrow("actual_date")));
json_data.put("receiver", visits.getString(visits.getColumnIndexOrThrow("receiver")));
json_data.put("observations", visits.getString(visits.getColumnIndexOrThrow("observations")));
json_data.put("gps_coordinates", visits.getString(visits.getColumnIndexOrThrow("gps_coordinates")));
In the LogCat:
{
"id_promoter":"1",
"id_establishment":"5",
"id_visit":"1",
"receiver":"brenda lopez",
"gps_coordinates":"10.4905567 -66.8710966",
"actual_date":"2012-11-27",
"id_form":"1",
"observations":"observaciones"
}
As you can see, its not te same order! Why is this?
I apologize for not taking the time of checking if someone else already asked this, but I'm in a little hurry, so... Sorry!! xD
Object keys are not ordered in JSON. If you need a specific order, I suggest you use an array:
[
{"id_promoter":"1"},
{"id_establishment":"5"},
{"id_visit":"1"},
{"receiver":"brenda lopez"},
{"gps_coordinates":"10.4905567 -66.8710966"},
{"actual_date":"2012-11-27"},
{"id_formu":"1"},
{"observations":"observaciones"}
]
It's gross, but order is what arrays are for.
Another approach is to define an array with the key names in the desired order. Then you can use your original object structure but access it through keys defined by the array. This takes more coding, obviously, but it can also solve your problem.
I want to work with Open Street Map (OSM). OSM keeps its data formats as flexible as possible by using key value pairs. I am developing an application for Android and I am going to send it a JSON string of OSM data. What should I do if I do not know what the JSON will look like in advance? What would be the best library?
Thanks for your help,
Chris
This may be what you are looking for
http://code.google.com/p/google-gson/
Cheers
First of all, you need to know if the JSON file contains an array or an object. If the first nonwhite space character is a [, it's an array, if it's a {, it's an object. Creating JSONArray when the first char is a { or vice versa will throw a Runtime Exception.
Second off all, once you have your JSONObject, you're going to want to get data from it. So you have to know the name of the keys to get the values, i.e.
myStreet = myJsonOjbect.getString("street name")
If you're not going to get data from it, what's the point of having the json file? Surely you can open the JSON in a Lint to see what the structure is.
hope this helps!