Same JSON Strings when converting to json string cross platform - java

If I have a json String {"k":"v","a":"b"}.
If I convert it into a json Object and then back to String in Java let say using Gson library and store it in some database.
And Also I convert it into json Object and back to String in Python , it is possible that I get the String as {"a":"b","k":"v"} , though json object will be same but now I cannot do a string match as the order is changed.
How can I solve this problem ?

There is no guarantee that order of json object keys will be same.
Json object is unordered by specefication: http://json.org/
An object is an unordered set of name/value pairs.
If you want some order, you should use json array instead of json object.
An array is an ordered collection of values.
see also: ECMAScript Language Specification

Ensure that the keys are always in sorted order when the JSON is serialized to the database. In Python you would write:
json.dumps(obj, sort_keys=True)
With GSON this is harder to do, you may need to use a different library.

Related

Scala: Transforming JSON string to ListMap and preserving insertion order

I have a JSON string that I am using within a Scala programme by converting it into a ListMap to perform some tests, and then returning the results in an output JSON, along with the original JSON as a value. I cannot use a schema as the JSONs are changeable. The original JSON string is for example:
val originalJSONString =
{
"outerKey1": "",
"outerKey2": "",
"outerKey3": {
"innerKey1": "",
"innerKey2": "",
"innerKey3": ""
}
}
When I convert it to a ListMap using the below code, it will preserve the order of the outer keys, but not the inner keys as Object doesn't preserve the order.
val jsonListMap = mapper.readValue[ListMap[String, Object]](originalJSONString)
If I create a JSON that just contains the "outerKey3" key and its values, and the following code, it will preserve the order, but naturally will not work on the whole of the originalJSONString. The JSONs will always only have nesting of two levels.
val jsonListMap = mapper.readValue[ListMap[String, ListMap[String, String]]](originalJSONString)
There must surely be some way within this code to convert the keys with string values to Object/String and the keys with Map/ListMap values (i.e. outerKey3) to a ListMap? I want it to infer which data type it should be creating.
I was thinking about creating a function, or using Either/Option but I'm not sure these are appropriate.
(I am aware that JSON is by definition unordered and Scala/Java do not preserve order for this reason. Unfortunately without being able to convert the necessary values to ListMap the final JSON is unordered and the humans who will be reading it - not querying it - want it in order. I do not want to return the original string as the formatting would make my querying of the output JSON a nightmare. Also I would like to know if inferring data type in this way is possible for many other data wrangling issues outside of preserving JSON key order!)
Thank you in advance!

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.

Can JSON field not be a string?

As far as I know, all JSON field names are string values. However, I encountered a code snippet that does a string check on the "keys" of JSON to see if it's a string, and if not, it throws an exception. It goes something like:
if (!(key instanceof String)){
throw new exception();}
Is this check necessary?
EDIT:
For example,
while (jp.nextToken() == JsonToken.FIELD_NAME){
String key = jp.getCurrentName();
}
This code snippet will only progress to JSON tokens that are strings, so I was wondering if a JSON could contain fieldnames that are not strings so that Jackson parser will simply skip those fieldnames.
From the JSON official website (and by proxy, the JSON Data Interchange Standard):
When creating an object, the key must be a String.
EDIT: As #SotiriosDelimanolis pointed out in the comments, this only applies to the format of the JSON file, not necessarily once parsed through a Java library.
Jackson, for example, can deserialize keys into custom types - #SotiriosDelimanolis

Converting JSON Object(s) from file using Java

I have a JSON file with no clue on how data will be in it nor the structure of data.
The only thing known is that it will have either an array of JSON objects or a single JSON object.
I need to get each object from the file and store it as a separate item. In case of array of objects in the file, I should get an array of JSON strings which I can store in DB.
Basically, I need to read this file and separate out each JSON object from it and store it in DB as a string.
One of the ways to do it was to use JACKSON ObjectMapper and assign these items to a Hashmap as key value pairs, but I am not sure though how it can be done If there are list of JSON Objects in the file.
Sample JSON File:
[
{
"name":"Bob",
"type":"Email",
"from":"a#a.com",
"to":"b#B.com",
"attachments":[...],
.
.
.
}
]
Do you know the Object structure that the JSON has(let it be Array or a single one) ? If Yes,
First load the json string form the file into an in memory string.
check the string for Array existence, by searching for '[',']' in the outer structure of multiple occurrences of '{' or '}'
once you know whether you have an array or a single object, you can pass it as object reference to either Jackson or GSON parsers
create in memory Array of JsonObject.class say List. It is actually better to enclose this List inside another class. say myJsonObjects and have a List inside it.
Let us see GSON parsers (by google), though Jackson can also be used in the similar implementation
Gson gson = new Gson();
if(isArray){
myJsonObjects jsonArray = gson.fromJson(jsonStringFromFile,myJsonObjects );
}
else{
gson.fromJson(jsonStringFromFile,JsonObject);
}
http://google-gson.googlecode.com/svn-history/trunk/gson/docs/javadocs/com/google/gson/Gson.html
Jackson is my favorite JSON-to-POJO library. It doesn't really matter where you're loading the JSON from (a URL or from the filesystem), there are handlers for several input sources.
Here's an example:
Map<String,Object> userData = mapper.readValue(new File("user.json"), Map.class);
As far as having an unknown number of JSON structures that you're about to parse, the first thing that comes to mind is to have a mapper for each type you're expecting. You could then wrap the parsing code in try/catch blocks so that if the first fails with whatever exception Jackson gives you when encountering an unexpected format, you can then try the next format and so on.
If you're just trying to generically parse JSON that you don't know the structure of beforehand, you can try something like this:
mapper.readValue(jsonString, new TypeReference<List<EntryType>>() {});
The documentation for Jackson is pretty good-- giving it a solid read-through should definitely help. Here's a good five minute tutorial: http://wiki.fasterxml.com/JacksonInFiveMinutes
I prefer use Gson:
Gson gson;
Map<String, Object>parameters=gson.fromJson(myString);
the rest is iterate the map, i hope help you

List<String> to Json String

How can I convert a List to a Json String?
I have managed to do it the other way round, but not this way.
I also don't know how I can specify the names of the keys then..
You can use the Gson Library.
List<String> list;
String json = new Gson().toJson(list);
Edited:
Just to have the complete answer here: The problem is that you are converting the json String into a List<String>. This way you are losing the relation key-value. The correct should be convert the json string into a HashMap<>.
It seems like your real problem is that when you originally turned the JSON string into a List, you threw away the keys. And that is not surprising, a List is not a natural representation of a JSON object (i.e. a thing with key - value pairs). You probably should have represented it as a Map.
But anyway, if you threw away the keys you've go a problem. You need to either you change your data structure to not throw the keys away, or reconstruct the JSON by inferring what the keys should be based on (for instance) their position in the list. (The latter could be a bit dodgy because the order of the name/value pairs in the original JSON should not signify anything ... and could be "random" or "implementation dependent".

Categories

Resources