Json Parsing Using Gson For Java

JSON parsing using Gson for Java

This is simple code to do it, I avoided all checks but this is the main idea.

 public String parse(String jsonLine) {
JsonElement jelement = new JsonParser().parse(jsonLine);
JsonObject jobject = jelement.getAsJsonObject();
jobject = jobject.getAsJsonObject("data");
JsonArray jarray = jobject.getAsJsonArray("translations");
jobject = jarray.get(0).getAsJsonObject();
String result = jobject.get("translatedText").getAsString();
return result;
}

To make the use more generic - you will find that Gson's javadocs are pretty clear and helpful.

Parsing JSON File using Gson

This is the working code which is running perfectly in my system:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import com.google.gson.JsonElement;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;

public class EntityName {

public static void main(String[] args) throws JsonIOException, JsonSyntaxException, FileNotFoundException {

File f = new File("others//entity-name.json");
JsonParser jsonParser = new JsonParser();
JsonElement jsonElement = jsonParser.parse(new FileReader(f));
JsonElement element = jsonElement.getAsJsonObject().getAsJsonObject("services").get("M");
System.out.println(element.getAsInt());
}

}

Here entity-name.json contains given json.

Using GSON to parse Json into a JAVA Object where the Json Elements may vary

I'm not sure if I understood your question right. As per my understanding, you are trying to convert a json object with an extra field which is not available in the java class. Frankly, I don't understand why you want that or if it's possible to start with. You can have a workaround by converting the json to Map.

Map map = gson.fromJson(jsonString, Map.class);

How to parse JSON string using GSON?

Create classes, add variables and tag them for Deserialization:

public class Root {
@SerializedName("objs")
public List<Obj> objects;
}

public class Obj {
@SerializedName("obj1")
public Obj1 obj1;
}

public class Obj1 {
@SerializedName("ID1")
public int ID1;

@SerializedName("ID2")
public int ID2;
}

Then Deserialize your JSON:

Gson gson = new Gson();
Root root = gson.fromJson(jsonString, Root.class);

Parsing nested JSON data using GSON

You just need to create a Java class structure that represents the data in your JSON. In order to do that, I suggest you to copy your JSON into this online JSON Viewer and you'll see the structure of your JSON much clearer...

Basically you need these classes (pseudo-code):

class Response
Data data

class Data
List<ID> id

class ID
Stuff stuff
List<List<Integer>> values
String otherStuff

Note that attribute names in your classes must match the names of your JSON fields! You may add more attributes and classes according to your actual JSON structure... Also note that you need getters and setters for all your attributes!

Finally, you just need to parse the JSON into your Java class structure with:

Gson gson = new Gson();
Response response = gson.fromJson(yourJsonString, Response.class);

And that's it! Now you can access all your data within the response object using the getters and setters...

For example, in order to access the first value 456, you'll need to do:

int value = response.getData().getId().get(0).getValues().get(0).get(1);

How to handle json element after parsing using GSON library?

The most generic way is to use Map<String, Object> to represent dynamic structure of JSON payload. In that case, we can always use Map#keySet() method to list all properties and we do not need any String[] to keep them. Also, lookup objects by key is faster than using array or List. If our object values have constant structure we can map it to POJO to have stable access to values in runtime. Below code shows both cases:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;

import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class GsonApp {

public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();

Gson gson = new GsonBuilder().create();

System.out.println("Use generic Map");
Type genericMapType = new TypeToken<Map<String, Object>>() {
}.getType();
Map<String, Object> map = gson.fromJson(new FileReader(jsonFile), genericMapType);
map.forEach((k, v) -> System.out.println(k + " => " + v));

System.out.println();
System.out.println();

System.out.println("Use Service Map");
Type serviceMapType = new TypeToken<Map<String, Service>>() {
}.getType();
Map<String, Service> serviceMap = gson.fromJson(new FileReader(jsonFile), serviceMapType);
serviceMap.forEach((k, v) -> System.out.println(k + " => " + v));
}
}

class Service {
private List<String> addresses;

@SerializedName("healthcheck_interval")
private int healthCheckInterval;
private String http;
private int port;

public List<String> getAddresses() {
return addresses;
}

public void setAddresses(List<String> addresses) {
this.addresses = addresses;
}

public int getHealthCheckInterval() {
return healthCheckInterval;
}

public void setHealthCheckInterval(int healthCheckInterval) {
this.healthCheckInterval = healthCheckInterval;
}

public String getHttp() {
return http;
}

public void setHttp(String http) {
this.http = http;
}

public int getPort() {
return port;
}

public void setPort(int port) {
this.port = port;
}

@Override
public String toString() {
return "Service{" +
"addresses=" + addresses +
", healthCheckInterval=" + healthCheckInterval +
", http='" + http + '\'' +
", port=" + port +
'}';
}
}

Above code prints:

Use generic Map
backup => {addresses=[127.0.0.1], healthcheck_interval=60, http=https, port=9001}
cognito => {addresses=[127.0.0.1], http=https, port=9012}
collector => {addresses=[127.0.0.1], healthcheck_interval=60, http=https, port=9000}
ds => {addresses=[127.0.0.1], http=https, port=9011}
insight-analytics => {addresses=[127.0.0.1], http=https, port=9013}
integrations => {addresses=[127.0.0.1], http=https, port=9014}
server => {addresses=[127.0.0.1], healthcheck_interval=60, http=https, port=9009}
vigile => {addresses=[127.0.0.1], http=https, port=9443}
walt => {addresses=[127.0.0.1], http=https, port=9010}


Use Service Map
backup => Service{addresses=[127.0.0.1], healthCheckInterval=60, http='https', port=9001}
cognito => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9012}
collector => Service{addresses=[127.0.0.1], healthCheckInterval=60, http='https', port=9000}
ds => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9011}
insight-analytics => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9013}
integrations => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9014}
server => Service{addresses=[127.0.0.1], healthCheckInterval=60, http='https', port=9009}
vigile => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9443}
walt => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9010}

Java Gson parse Json object to array

TL;DR: See "Using Deserializer" section at the bottom for parsing straight to array.


That JSON does not contain any arrays. An array would use the [...] JSON syntax.

Normally, a JSON object would map to a POJO, with the name in the name/value pairs mapping to a field of the POJO.

However, a JSON object can also be mapped to a Map, which is especially useful when the names are dynamic, since POJO fields are static.

Using Map

The JSON object with numeric values as names can be mapped to a Map<Integer, ?>, e.g. to parse that JSON to POJOs, do it like this:

class Root {
@SerializedName("Outer")
public Map<Integer, Outer> outer;
@Override
public String toString() {
return "Root[outer=" + this.outer + "]";
}
}
class Outer {
@SerializedName("Attr1")
public int attr1;
@SerializedName("Attr2")
public int attr2;
@Override
public String toString() {
return "Outer[attr1=" + this.attr1 + ", attr2=" + this.attr2 + "]";
}
}

Test

Gson gson = new GsonBuilder().create();
Root root;
try (BufferedReader in = Files.newBufferedReader(Paths.get("test.json"))) {
root = gson.fromJson(in, Root.class);
}
System.out.println(root);

Output

Root[outer={0=Outer[attr1=12345, attr2=67890], 1=Outer[attr1=54321, attr2=9876]}]

Get as Array

You can then add a helper method to the Root class to get that as an array:

public Outer[] getOuterAsArray() {
if (this.outer == null)
return null;
if (this.outer.isEmpty())
return new Outer[0];
int maxKey = this.outer.keySet().stream().mapToInt(Integer::intValue).max().getAsInt();
Outer[] arr = new Outer[maxKey + 1];
this.outer.forEach((k, v) -> arr[k] = v);
return arr;
}

Test

System.out.println(Arrays.toString(root.getOuterAsArray()));

Output

[Outer[attr1=12345, attr2=67890], Outer[attr1=54321, attr2=9876]]

Using Deserializer

However, it would likely be more useful if the conversion to array is done while parsing, so you need to write a JsonDeserializer and tell Gson about it using @JsonAdapter:

class Root {
@SerializedName("Outer")
@JsonAdapter(OuterArrayDeserializer.class)
public Outer[] outer;

@Override
public String toString() {
return "Root[outer=" + Arrays.toString(this.outer) + "]";
}
}
class OuterArrayDeserializer implements JsonDeserializer<Outer[]> {
@Override
public Outer[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
// Parse JSON array normally
if (json.isJsonArray())
return context.deserialize(json, Outer[].class);

// Parse JSON object using names as array indexes
JsonObject obj = json.getAsJsonObject();
if (obj.size() == 0)
return new Outer[0];
int maxKey = obj.keySet().stream().mapToInt(Integer::parseInt).max().getAsInt();
Outer[] arr = new Outer[maxKey + 1];
for (Entry<String, JsonElement> e : obj.entrySet())
arr[Integer.parseInt(e.getKey())] = context.deserialize(e.getValue(), Outer.class);
return arr;
}
}

Same Outer class and test code as above.

Output

Root[outer=[Outer[attr1=12345, attr2=67890], Outer[attr1=54321, attr2=9876]]]

Java GSON Json partial parsing

You can avoid using a String for your entity_json by using Gson's JsonObject.

Here is my revised Entity class:

import com.google.gson.JsonObject;

public class MyEntity {

private String entity_id;
private String entity_name;
private JsonObject entity_json;

// getters and setters not shown

}

Then you can populate instances as follows:

MyEntity myEntityOne = new Gson().fromJson(JSON_ONE, MyEntity.class);
MyEntity myEntityTwo = new Gson().fromJson(JSON_TWO, MyEntity.class);

System.out.println(myEntityOne.getEntity_json());
System.out.println(myEntityTwo.getEntity_json());

In the above code, JSON_ONE and JSON_TWO are just strings containing the two sample JSONs from your question.

The console prints out the following (snipped for brevity):

{"employee_id":"e01","employee_name":"john","employee_phone_numbers":["1234567","8765433"]}
{"invoice_id":"1011","items":{"item_id":"1","quantity":"3","price":"$100"},"date":"01-01-2020"...

You can, of course, now use Gson to further manipulate each entity_json field as needed, since each one is itself a valid JSON object.



Related Topics



Leave a reply



Submit