How to copy all the values from one JSONObject to another? - java

I understand that it's perfectly possible to copy each individual component over one by one, but it's extremely messy to do and rather ugly. Isn't there a simpler way to copy all the values from one JSONObject to another? Important to note, I am using json-lib. I'm not opposed to switching tools if it's absolutely necessary. Point is, this is a rather inefficient way of doing things.

After hours of searching, I finally found the answer. I'm sort of embarrased that it's this simple.
~
Json-lib has a beautiful feature that allows you to take your current JSONObject and parse the entirety of the JSONObject into a String. And there already exists a method to build a JSONObject from a String. Therefore, all you need to do is turn the JSONObject into a String, and then back into a JSONObject. You could store the string as a variable (or use it as a return value), then simply take your preexisting JSONObject reference and use the method to rebuild the JSONObject from the String. Simple as that.
EDIT - thought I would give a quick code example
JSONObject a = /* pretend a has 100 elements inside */
String temp = a.toString();
JSONObject b = JSONObject.fromObject(temp);
String temp2= b.toString();
if(temp.equals(temp2)){System.out.println("Well done.");}

Related

Parsing JSON string and preserving key-data order when using json-simple without manually constructing HashMap

I know that this topic has been talked about, and the use of a LinkedHashMap is a 'hacky' way to maneuver this, but if I'm given thousands of JSON strings as input, and eventually want to output them back in their original form, is there anyway to preserve the order without manually constructing LinkedHashMaps.
For example a string like this
{"key":1,"surname":"Reed","given":"Ryan","address":{"state":"CA","postal":"90210"},"gender":"M"}
Right now if I parse the object like so:
JSONObject jsonObject = (JSONObject) parser.parse(str);
System.out.println(jsonObject);
My output will look like this:
{"surname":"Reed","gender":M,"address":{"postalCode":"90210","state":"CA"},"key":1,"given":"Ryan"}
Is there anyway I can get the output to match exactly like the given input?
In Json property structure, order does not matter. but if you have specific order in your mind you can use Jackson to order them in you desirable way, both in your server and client apps.
https://www.baeldung.com/jackson
http://www.davismol.net/2016/10/24/jackson-json-using-jsonpropertyorder-annotation-to-define-properties-serialization-order/
I think it is impossible by default.
You can refer to this RFC https://www.ietf.org/rfc/rfc4627.txt
An array is an ordered sequence of zero or more values.
If you want to hack it you can override the data structure and use the data structure which preserves the order.

javax.json objects have same methods, but they're not implementations of a common interface. How to cast?

I'm dealing with the strange javax.json library. So here's the problem:
I need to cast an Object of type JsonValue to either JsonObject or JsonArray so I can call the methods getJsonObject and getJsonArray of it. Both JsonArray and JsonObject have the same method names with the same functionalities but they're not implemented methods, they are methods defined on each of them! See: JsonObject, JsonArray.
The obvious solution would be to verify the type and then cast depending on the verified type, like this:
if (current.getValueType().equals(JsonValue.ValueType.OBJECT)) {
current = ((JsonObject) current).getJsonObject(node);
} else if (current.getValueType().equals(JsonValue.ValueType.ARRAY)) {
current = ((JsonArray) current).getJsonObject(node);
}
but it'd require too many repetitions on my code. So I ask:
1) If both JsonObject and JsonArray have the same methods, why they're not implementations of some interface?
2) Is there a more elegant way to cast the object to JsonObject or JsonArray at the same time by using some trick? Do you know any way to make this situation better?
Although the 2 methods on the 2 different objects have the same name, their signatures are in fact different. JsonObject#getJsonObject(String) accepts a String key identifying the value to pull from a JSON object of key-value pairs. JsonArray#getJsonObject(int) accepts an int index identifying which element to pull the value from in a JSON array.
In this case, there is no appropriate common interface that the 2 classes can share. Your code will have to know whether to inspect a JSON object or a JSON array and cast accordingly.
Since the 2 methods in question do not have the same signature, there are not other alternatives for calling them in a "common way". You could potentially use reflection, but this risks making the code more confusing. For example, Apache Commons includes MethodUtils#invokeMethod. You could potentially use that to invoke any method named "getJsonObject", accepting any kind of object (either String or int). Although using this would make it "common code" across both cases, it's potentially confusing for people reading the code later. They'd have to keep track of the fact that this is using reflection, and that the passed argument might be either String or int, and that it really all works out thanks to it being either a JSON object or array. Instead, I would favor just doing the downcast in this case.
Chris is right, Your code will have to know whether to inspect a JSON object or a JSON array and cast accordingly. However, if you are ok with adding an external library, I would recommend gson for parsing Json
This library has JsonElement class which should fit good in your case. look at this to see how it works

How to modify an existing jsonobject in Java

I have an existing jsonobject from the javax.json.JsonObject class.
I can't for the life of me figure out how I can modify the existing values in it. Ideally I'd like to do something like this:
if(object.getString("ObjectUUID").length()==0){
object.put("ObjectUUID", UUID.randomUUID().toString());
}
According to the API you aren't allowed to modify that map.
http://docs.oracle.com/javaee/7/api/javax/json/JsonObject.html
This map object provides read-only access to the JSON object data, and attempts to modify the map, whether direct or via its collection views, result in an UnsupportedOperationException.
Currently I'm getting around the problem with a quick hack but there must be a better solution than this:
if(object.getString("ObjectUUID").length()==0){
JsonObjectBuilder job = Json.createObjectBuilder();
job.add("ObjectUUID", UUID.randomUUID().toString());
for(String key : object.keySet()){
if(!key.equals("ObjectUUID")){
job.add(key, object.get(key));
}
}
object = job.build();
}
So the question how do you modify an existing jsonobject?
Without knowing the structure of the JSON object, it's a bit difficult to provide an answer that addresses your specific problem. The JsonObject instance is immutable, so you can't update it like Jackson's ObjectNode. As you've probably found, the JsonObject.add() method is basically useless, and depending on the implementation, may yield an UnsupportedOperationException. It's puzzling why it exists in the first place.
The way to modify the object is to create a JsonObjectBuilder instance that wraps the original JsonObject. If the object instance was your original JsonObject you'd probably want to do something like this:
if(object.getString("ObjectUUID").length()==0){
object job = Json.createObjectBuilder(object)
.add("ObjectUUID", UUID.randomUUID().toString())
.build();
}
This took me a while to understand myself, and it gets a but more verbose if you have nested objects, etc.. If you're updating or replacing an object or array, you don't need to explicitly remove it before adding. There's pros and cons of the approach, but it beats the monthly ceremony of updating Jackson on a monthly basis :)
I think there is no other way to modify a javax.json.JsonObject.
You should consider using jackson-databind.
GSON Guide;
obj.addProperty("Id", "001");
System.out.println("Before: " + obj.get("Id")); // 001
obj.addProperty("Id", "002");
System.out.println("After: " + obj.get("Id")); // 002

Java - how to parse both json arrays and objects

i am using the org.json package in Java (Android) and I am just stumbled with a simple problem.
The webserver returns an array if everything is okay, but an json object { error : true, ...} if something went wrong.
How can I parse that into a common object - I mean both arrays and objects are json after all, but it seems JSONArray and JSONOBject don't share an interface in common.
Am I missing something?
Use JSONTokener.nextValue() and check if the result is a JSONObject or a JSONArray (using instanceof).
The real answer is ... fix the webserver and have it return a consistant result. Otherwise, you basically are going to have to manually inspect the returned data to see what it is.
Another option is catching the JSONException the constructor for JSONArray will throw when it isn't an array which would indicate to you that you should try JSONObject.

Parse a JSON package in Android

I'm having some difficulties parsing a JSON package in Android.
I currently have everything set up so the JSON is an array of objects, then each object has an array of attributes. For example, say I have an object called Colors in my package. Then each Color entry would be in the Colors object. Each Color entry would also have entries for R, G, B values.
This type, I can deal with fine. However, I'm now running into an instance where one of those entries (where the R,G,B values would be) has an array within it. I'm not sure how to go about accessing that and processing it.
I'm going to update with an example of the JSON package, since I'm worried I wasn't very clear.
Edit: Here's the JSON. Say I want to access the R value in the ColorOverlays.
{"Package":[
{"Things":[{"ProgramId":73,"TypeId":68,"CategoryId":null,"CategoryName":null,"ThingId":121,"ThingName":"Mahalo","ThingDescription":"Get your festival on and snap some shots!","ThingPrice":0.00,"SellerProductId":null,"Number2":1342655700,"Number1":1342655700,"IsAvailable":true,"ImageOverlays":[{"ThingId":121,"ThingOverlayId":295,"ImageOverlayBase64":null,"ImageOverlayFileTypeExtension":null,"Width":1024,"Height":1024,"A":1.00000,"BlendModeId":1,"OrderNum":2,"IsUseSource":false}],"ColorOverlays":[{"ThingId":121,"ThingOverlayId":294,"R":157.00000,"G":71.00000,"B":187.00000,"A":0.52873,"BlendModeId":6,"OrderNum":1}],"ThingsampleImageBase64":null,"ThingsampleImageFileTypeExtension":"","ThingsampleImageWidth":546,"ThingsampleImageHeight":546,"Captures":[{"ThingCaptureId":87,"ThingId":121,"CaptureFrameOverlayId":null,"IsRemoved":false,"AddDate":1342637814,"LastUpdated":1342637814,"Saturation":0.0,"Contrast":0.0,"Brightness":0.0,"Low":null,"Mid":null,"High":null,"IsBlackWhite":null,"IsInvert":null,"IsSepia":null}],"IsRemoved":false},{"ProgramId":73,"TypeId":68,"CategoryId":null,"CategoryName":null,"ThingId":122,"ThingName":"Lots of Love","ThingDescription":"Use this one!","ThingPrice":0.00,"SellerProductId":null,"Number2":1342667100,"Number1":1342667100,"IsAvailable":true,"ImageOverlays":[{"ThingId":122,"ThingOverlayId":298,"ImageOverlayBase64":null,"ImageOverlayFileTypeExtension":null,"Width":1024,"Height":1024,"A":1.00000,"BlendModeId":4,"OrderNum":3,"IsUseSource":false}],"ColorOverlays":[{"ThingId":122,"ThingOverlayId":296,"R":213.00000,"G":86.00000,"B":143.00000,"A":0.77777,"BlendModeId":4,"OrderNum":1},{"ThingId":122,"ThingOverlayId":297,"R":127.00000,"G":127.00000,"B":127.00000,"A":0.50000,"BlendModeId":1,"OrderNum":2}],"ThingsampleImageBase64":null,"ThingsampleImageFileTypeExtension":"","ThingsampleImageWidth":546,"ThingsampleImageHeight":546,"Captures":[{"ThingCaptureId":88,"ThingId":122,"CaptureFrameOverlayId":null,"IsRemoved":false,"AddDate":1342649164,"LastUpdated":1342649164,"Saturation":0.0,"Contrast":0.0,"Brightness":0.0,"Low":null,"Mid":null,"High":null,"IsBlackWhite":null,"IsInvert":null,"IsSepia":null}],"IsRemoved":false}]}
]}
If this is not something that you would throw away after the first use, then you might consider taking this up a level by modeling Java objects after your domain.
Use any online JSON visualizer to see your JSON in 3D.
Then, follow the following tutorial.
http://java.sg/parsing-a-json-string-into-an-object-with-gson-easily/
A sample of your code would be most helpful to try to help. Depending on how your RGB value array is built and passed. If it's a simple comma delimited string, then you could do:
try {
JSONArray jArray = new JSONArray(jString);
for (int i=0; i<jArray.length(); i++) {
JSONObject jo = jArray.getJSONObject(i);
String RGBVal = jo.getString("rgb_list");
String[] rgbArray = RGBVal.split(",");
....
Again, depends on how the entry is passed in JSON string.
Nevermind...

Categories

Resources