How to convert string array to object using GSON/ JSON? - java

I have a json like this:
[
[
"Passport Number",
"NATIONALITY",
"REASONS"
],
[
"SHAIS100",
"INDIA",
""
],
[
"",
"",
"Agent ID is not matched."
],
[
"",
"",
""
]
]
I want to populate this to ArrayList<String[]>,Please tell me how to do?
And empty strings should not convert as null.

That's very simple, you just need to do the following:
1.- First create the Gson object:
Gson gson = new Gson();
2.- Then get the correspondent Type for your List<String[]> (Note that you can't do something like List<String[]>.class due to Java's type erasure):
Type type = new TypeToken<List<String[]>>() {}.getType();
3.- Finally parse the JSON into a structure of type type:
List<String[]> yourList = gson.fromJson(yourJsonString, type);

Take a look at Gson docs
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};
(Serialization)
gson.toJson(ints); ==> prints [1,2,3,4,5]
gson.toJson(strings); ==> prints ["abc", "def", "ghi"]
(Deserialization)
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
==> ints2 will be same as ints
Tis is important for you: We also support multi-dimensional arrays, with arbitrarily complex element types
For null objects, Gson by default will not convert as null. Ref.
But you can configure to scan those nulls attributes if you want to do it after.
The default behaviour that is implemented in Gson is that null object fields are ignored. This allows for a more compact output format; however, the client must define a default value for these fields as the JSON format is converted back into its Java.
Here's how you would configure a Gson instance to output null:
Gson gson = new GsonBuilder().serializeNulls().create();
In your problem maybe you don't need to configure that.
I hope it helps.

Related

How to parse raw values from JSON array items with Jackson?

Using Jackson deserialization it would be great to have an option
to deserialize JSON array of items (of any nature: object, number, string) to a Java array of String.
I see that #JsonRawValue allows to have similar functionality for nested fields.
Is it possible to implement the same for "top level" objects?
void test(){
var payload = """ [
{"a": 1, "b": "hello"},
{"a": 2, "b": "bye"},
"something"
]
""";
// What else is required to get the effect of #JsonRawValue ?
String[] rawItems = new ObjectMapper().readValue(payload, String[].class);
assertEquals("""{"a": 1, "b": "hello"}""", rawItems[0]);
assertEquals("""{"a": 2, "b": "bye"}""", rawItems[1]);
assertEquals("\"something\"", rawItems[2]);
}
You can convert the payload to com.fasterxml.jackson.databind.node.ArrayNode and then iterate through elements (JsonNode in this case) and add them to a List<String> (which you can then convert to String[] if you want).
One thing to be aware of - the formatting will not be as you expect. JsonNode has two methods - toString() which deletes all the white space and toPrettyString which adds whitespaces and newlines to the final String
String payload = """
[
{"a": 1, "b": "hello"},
{"a": 2, "b": "bye"},
"something"
]
""";
ArrayNode items = new ObjectMapper().readValue(payload, ArrayNode.class);
List<String> rawItemsList = new ArrayList<>();
for (JsonNode jsonNode : items) {
rawItemsList.add(jsonNode.toString());
}
// You can just keep using the rawItemsList, but I've converted it to array since the question mentioned it
String[] rawItemsArr = rawItemsList.toArray(new String[0]);
assertEquals("""
{"a":1,"b":"hello"}""", rawItemsArr[0]);
assertEquals("""
{"a":2,"b":"bye"}""", rawItemsArr[1]);
assertEquals("\"something\"", rawItemsArr[2]);

Read the outer-most JSON object but not the inner ones using Jackson?

This is similar to this question but it's a little different.
Let's say I have a json document defined like this:
[
{ "type" : "Type1",
"key1" : "value1" },
{ "type" : "Type2",
"key2" : "value2" }
]
I want to read this json document into a list of strings (List<String>). I only want to read the outer-most list into the Java List, the json objects inside the list should be left as-is inside the list. The result should be equivalent to this (I ignore newlines etc):
var myList = List.of("{\"type\": \"Type1\", \"key1\": \"value1\"}, {\"type\": \"Type2\", \"key2\": \"value2\"}")
Note that I don't want to create any DTO to hold some intermediate representation. I just want everything below the "list" to be represented "as-is".
How can I achieve this?
I'm using Jackson 2.12.1.
If you don't want to hold intermediate representation in a DTO, then one way in which the required deserialization can be achieved is:
// Create a ObjectMapper (of type com.fasterxml.jackson.databind.ObjectMapper)
ObjectMapper mapper = new ObjectMapper();
// Read the json string into a List. This will be deserialized as a collection of LinkedhashMap
List<LinkedHashMap> list = mapper.readValue(getInputString(), List.class);
//Iterate over the deserialized collection and create a JSONObject from every LinkedHashMap
List<String> result = list.stream()
.map(map -> new JSONObject(map).toString())
.collect(Collectors.toList());
This will produce:
[{"key1":"value1","type":"Type1"}, {"key2":"value2","type":"Type2"}]
Downside of this approach is, it takes a hit on performance.

Print JSON with ordered properties

I have JSON with objects in specific order:
{
"Aaa": {
"Langs": {
"Val": [
"Test"
],
"Pro": [
"Test2"
]
}
},
"Bbb": {
"Langs": {
"Val": [
"Test"
],
"Pro": [
"Test2"
]
}
},
"Ddd": {
"Langs": {
"Val": [
"Test"
],
"Pro": [
]
}
},
}
And I would like to add new object Ccc between Bbb and Ddd. I tried to configure object mapper like this:
ObjectMapper mapper = new ObjectMapper()
.enable(SerializationFeature.INDENT_OUTPUT)
.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
and then print with this code, but Ccc ends at the end of file.
DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
prettyPrinter.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
//Write whole JSON in FILE
String finalJson = mapper.writer(prettyPrinter).writeValueAsString(rootFlores);
finalJson = finalJson.replaceAll("\\[ ]", "[" + System.lineSeparator() + " ]");
finalJson = finalJson.replaceAll("/", "\\\\/");
Files.write(Paths.get("DictionaryFlores_new.json"), Collections.singleton(finalJson));
Is here a way how to print JSON ordered?
Jackson deserialization/serialization does not sort properties
According to this answer, the Jackson SORT_PROPERTIES_ALPHABETICALLY only applies to POJO properties, not Maps. In JSON there is no difference between a Map and an Object, so you need to set the order in the Map first by using a LinkedHashMap or TreeMap
By definition, the keys of an object are unordered. I guess some libraries could offer an option to control the order of the keys when stringifying, but I wouldn't count on it.
When you need a certain order in json, you need to use an array. Of course, then you'd have to move the keys to a property in the child objects, and then the resulting array could only be indexed by number (not by the key). So then you might have to do additional processing to covert the data structure in the JSON to the data structure you really want to process.
Since you seems ready to use regex to update a JSON, I would suggest a "safer" approach. Don't try to create a pattern that would unsure that you don't update a value somewhere.
Iterate you values, on object at the time. Stringify the object and append the String yourself. That way, you are in charge of the object order. Example :
StringBuilder sb = new StringBuilder("{");
List<JsonPOJO> list = new ArrayList<>();
//populate the list
for(JsonPOJO pojo : list){
sb.append(pojo.stringify()).append(",");
}
sb.setLength(sb.length() - 1); //remove the last commma
sb.append("}");
Here, you are only managing the comma between each JSON object, not create the "complex" part about the JSON. And you are in full control of the order of the value in the String representation, it will only depend on the way you populate the List.
Note: sorry for the "draft" code, I don't really have access to my system here so just write this snippet to give you a basic idea on how to "manage" a JSON without having to recreating an API completely.
Note2: I would note suggest this unless this looks really necessary. As you mention in a comment, you are have only the problem with one key where you already have a JSON with 80000 keys, so I guess this is a "bad luck" scenario asking for last resort solution ;)

Deserialize nested JSON array in Java with Gson

Something like this. http://jsonlint.com/ says it is valid. Json inside {} simplified for this example.
[[0,{"ok":true},[]],[1,{"ok":false},[]]]
Or with indents:
[
[0, {
"ok": true
},
[]
],
[1, {
"ok": false
},
[]
]
]
This is class for object JSONClass.
public class JSONClass {
boolean ok;
}
If I got it right, this JSON string is array of arrays, latter containing some ID, actual JSON data and empty array. How could I deserialize that?
This doesn't work. I also tried making class with subclasses, didn't work out.
JSONClass[] t = g.fromJson(json, JSONClass[].class);
Well, you have an array of arrays here. Gson will let you convert the JSON objects themselves into the class you want - but you'll have to call gson.fromJson() on each of them separately.
Given String json containing your json, something like this should work:
Gson gson = new Gson();
JsonParser jsonParser = new JsonParser();
JsonArray jsonArray = jsonParser.parse(json).getAsJsonArray();
for (JsonElement e: jsonArray) {
JSONClass o = gson.fromJson(e.getAsJsonArray().get(1), JSONClass.class);
}
Essentially, the JsonParser will convert your text into a JsonElement, which is the Gson base class for Json arrays and objects. We can iterate over the elements of the JsonArray which we parsed our text into, which in turn is another array of the format [id, object] - and for each element, take the object portion, and deserialize that into a POJO.

JSON mapper for Nested objects and arrays

I have a Json String from a webservice response.
This JSON sting has nested objects and arrays. I have tried to map it with java objects using jackson and GSON but i am getting errors in both the cases.
This is my Json:
{"events": [{
"Code": "4",
"eventDataSet": {
"Bar":{"EvDesc":"WRAP_UP"},
"Foo":{
"AcssId":"**1234",
"EvCSId":"12‌​34",
"custId":"3501234","Recid":"bknz"
}
}
]}
I want to pull the values of Bar and Foo objects from this json.
Please suggest how can i map such type of responses.
Libraries such as Gson and Jackson shouldn't have any trouble de-serializing valid JSON Strings.
Most probably the problem is with object types you're using to de-serialize your inputs.
You can use this site to generate POJO from one of your JSON responses. Input your JSON and select JSON as Source Type.
Then, with Gson:
Gson gson = new GsonBuilder().create();
Person p = gson.fromJson(inputString, Example.class);
Your json seems to have some problem. Here is modified json, and I am able to convert it to Object using jackson.
{
"events": [{
"code": "4",
"eventDataSet": {
"bar": {
"evDesc": "WRAP_UP"
},
"foo": {
"acssId": "**1234",
"evCSId": "12??34",
"custId": "3501234",
"recid": "bknz"
}
}
}]
}

Categories