How to parse Json with following structure - java

[
{
"updated_at":"2012-03-02 21:06:01",
"fetched_at":"2012-03-02 21:28:37.728840",
"description":null,
"language":null,
"title":"JOHN",
"url":"http://rus.JOHN.JOHN/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f4791da203d0c2d76000035",
"modified":"2012-03-02 23:28:58.840076"
},
{
"updated_at":"2012-03-02 14:07:44",
"fetched_at":"2012-03-02 21:28:37.033108",
"description":null,
"language":null,
"title":"PETER",
"url":"http://PETER.PETER.lv/rss.php",
"icon_url":null,
"logo_url":null,
"id":"4f476f61203d0c2d89000253",
"modified":"2012-03-02 23:28:57.928001"
}
]

First create one class (Json_obj) for your json data.Then you can try this :
String json_str='[ { "updated_at":"2012-03-02 21:06:01", "fetched_at":"2012-03-02 21:28:37.728840", "description":null, "language":null, "title":"JOHN", "url":"http://rus.JOHN.JOHN/rss.php", "icon_url":null, "logo_url":null, "id":"4f4791da203d0c2d76000035", "modified":"2012-03-02 23:28:58.840076" }, { "updated_at":"2012-03-02 14:07:44", "fetched_at":"2012-03-02 21:28:37.033108", "description":null, "language":null, "title":"PETER", "url":"http://PETER.PETER.lv/rss.php", "icon_url":null, "logo_url":null, "id":"4f476f61203d0c2d89000253", "modified":"2012-03-02 23:28:57.928001" } ]';
Gson gson = new Gson();
Json_obj json_obj = gson.fromJson(json_str, Json_obj.class);
Now your json data is converted in an object.You can fetch any value from that object.

I suggest you just use jackson library instead.
You can just quickly have
ObjectMapper mapper = new ObjectMapper () // this reads json to Pojo and writes Pojo to json
YourPojoClass obj = mapper.readValue (....)
Reference: mkyong.com/java/jackson-2-convert-java-object-to-from-json

Related

Json Parsing: How to fetch "body" data inside "body array" using Gson (or better in other java library or notation supported)?

My Rest API is returning the following response, in which only the inner list is required, all data shall be discarded:
{
"meta": [],
"links": [],
"body": [
{
"meta": [],
"links": [],
"body": {
"field1": "value1",
"fieldn": "valuen"
} // <-----
},
{
"meta": [],
"links": [],
"body": {
"field1": "value1",
"fieldn": "valuen"
} // <-----
}
]
}
Is there any way in Gson or another other java library to fetch an array of the body or a straightforward way of doing that? Or maybe even using standard of java 8?
Or, should I use a standard iterator as follows:
//Old way to do this
JSONArray BodyArr = (JSONArray) jsonObject.get("Body");
Iterator<JSONObject> itBody = BodyArr.iterator();
int teller = 0;
while (itBody.hasNext()) {
JSONObject bodyObj = itBody.next();
JSONObject body = (JSONObject) bodyObj.get("Body");
}
Also in mysql we have way to do that using notation ($.body.body[] etc.). Is there any notational way to fetch the object
I think we have a nicely written article on this.
Json object iteration
If you have a class that represents an object in the array, then you can deserialize the JSONArray to an array of that class using public <T> T fromJson​(JsonElement json, java.lang.Class<T> classOfT) throws JsonSyntaxException on the Gson class:
class BodyItem {
public String[] meta;
public String[] links;
public String field1;
public String fieldn;
}
public BodyItem[] getBodyItems(final Gson gson, final JsonObject jsonObject) {
final JsonElement body = jsonObject.get("body");
return gson.fromJson(body, BodyItem[].class);
}
public static void main(final String[] args) {
final String response = "<your REST API JSON response>";
final Gson gson = new Gson();
final JsonObject jsonObject = gson.fromJson(response, JsonObject.class);
final BodyItem[] bodyItems = getBodyItems(gson, jsonObject);
}
If you want a more notational way of accessing fields in Gson objects, you can use JsonObject's convenience accessors:
JsonArray getAsJsonArray​(java.lang.String memberName)
JsonObject getAsJsonObject​(java.lang.String memberName)
JsonPrimitive getAsJsonPrimitive(java.lang.String memberName)
And then with a JsonArray, you can iterate with for (final JsonElement element : jsonArray) or .forEach, and you can get JsonElements with the JsonElement get(int i) accessor.
So, say you had your original JsonObject response and wanted to get the value of body.field1 in the second element of the body list, you might do:
String value = jsonObject
.getAsJsonArray("body")
.get(1)
.getAsJsonObject()
.getAsJsonObject("body")
.getAsJsonObject("field1");

apply gson UPPER_CAMEL_CASE for specific sub-json

I have these messages arriving from SQS:
{
"eventID": "zzz",
"eventName": "MODIFY",
"eventVersion": "1.1",
"eventSource": "aws:dynamodb",
"awsRegion": "us-east-1",
"dynamodb": {
"ApproximateCreationDateTime": 1521976320,
"Keys": {
"key_1": {
"S": "yyy"
},
"key_2": {
"S": "xxx"
}
},
"SequenceNumber": "123",
"SizeBytes": 321,
"StreamViewType": "KEYS_ONLY"
},
"eventSourceARN": "arn:aws:dynamodb:us-east-1:eventSourceARN",
"itemType": "myItem"
}
I want to use gson library to convert this json string into a Record object (com.amazonaws.services.dynamodbv2.model.Record) which contains a StreamRecord object (com.amazonaws.services.dynamodbv2.model.StreamRecord) that represents the dynamodb sub json.
problem is that the inner fields of the dynamodb object are PascalCase while the other fields are normal camelCase.
This code:
Gson gson = new GsonBuilder()
//.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
String json = <the json from the example above>
Record record = gson.fromJson(json, Record.class);
log.info("record="+record.toString());
StreamRecord dynamodb = record.getDynamodb();
log.info("dynamodb="+dynamodb.toString());
Map<String, AttributeValue> keys = dynamodb.getKeys();
log.info("keys="+keys.toString());
prints this log (UPPER_CAMEL_CASE commented out) :
record={EventID: zzz,EventName: MODIFY,EventVersion: 1.1,EventSource: aws:dynamodb,AwsRegion: us-east-1,Dynamodb: {},}
and then throws Null Pointer exception because the dynamoDb object is empty - because my json string is UPPER_CAMEL_CASE, while in the object its normal camelCase.
I want to apply FieldNamingPolicy.UPPER_CAMEL_CASE only for the dynamodb sub json.
perhaps somehow using FieldNamingStrategy ?
The json is given and I cannot change its schema.
I also can't change the fact that I get it as string.
see AWS API:
https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_Record.html
https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_StreamRecord.html
You seem to want the following naming strategy:
private static final Gson gson = new GsonBuilder()
.setFieldNamingStrategy(field -> {
if ( field.getDeclaringClass() == StreamRecord.class ) {
return FieldNamingPolicy.UPPER_CAMEL_CASE.translateName(field);
}
return FieldNamingPolicy.IDENTITY.translateName(field);
})
.create();
I usually never use naming strategies in favor of the #SerializedName annotation though, just to be more precise when declaring mappings.

Java map object, which contains JSON string fields to string

I have faced problem, while mapping my object to JSON.
I have an object, which I need to convert to propper JSON, but some of my object's String fields are already in JSON format:
Sdr sdr = new Sdr();
sdr.setLocation_area(("location_area"));
sdr.setEvent_info(("{\"chargeableDur\":0}"));
sdr.setAgent_info("{\"scp\":\"NAVI\",\"stack\":\"CAP2\"}");
sdr.setService_info(("{\"bcap\":\"8090A3\",\"balID\":55969859}"));
sdr.setStarttime(("starttime"));
For JSON mapping I am using ObjectMapper:
public String toJsonString() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
logger.error(e.getMessage());
}
return toString();
}
However, ObjectMapper fails to map Strings, that already contains JSON correctly, and after mapping I get this type of JSON:
{
"event_info":""{\"chargeableDur\":0}",
"location_area":"location_area",
"agent_info":"{\"scp\":\"NAVI\",\"stack\":\"CAP2\"}",
"service_info":""{\"bcap\":\"8090A3\",\"balID\":55969859}",
"starttime":"starttime"
}
I want ObjectMapper to map my object like that:
{
"event_info":{
"chargeableDur":0
},
"location_area":"location_area",
"agent_info":{
"scp":"NAVI",
"stack":"CAP2"
},
"service_info":{
"bcap":"8090A3",
"balID":55969859
},
"starttime":"starttime"
}
Seems that your json result is stringified. Try to put the string result in separate JSONObject as
return new JSONObject(mapper.writeValueAsString(this)).toString();

how to deserialize a json object to collection using jackson

I want to deserialize a json like this
{
"0":{"name":"Alice"},
"1":{"name":"Bob"}
}
to a java collection( set or list, not map).
I want to change the default behavior of CollectionDeserializer to support this and config it as a global configuration. Any way to to this?
If you really have this structure (an object as a container and not an array, which could be handled much easier):
import com.fasterxml.jackson.databind.*;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\"0\":{\"name\":\"Alice\"}, \"1\":{\"name\":\"Bob\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode obj = mapper.readValue(json, JsonNode.class);
Iterator<Map.Entry<String, JsonNode>> userEntries = obj.fields();
while(userEntries.hasNext()){
Map.Entry<String, JsonNode> userEntry = userEntries.next();
System.out.println(userEntry.getKey() + " => " + userEntry.getValue());
}
}
}
You can achieve this task using gson api.
The code is as follows:
String yourJson = "{\"0\":{\"name\":\"Alice\"}, \"1\":{\"name\":\"Bob\"}}";
Gson gson = new Gson();
Type tarType = new TypeToken<Map<String,Map<String,String>>>(){
}.getType();
gson.fromJson(yourJson, tarType);
For this you need to add following:
com.google.gson.Gson
Why not to turn your JSON document into an array as:
{"persons":[{"name":"Alice"},{"name":"Bob"}]}
Then define a corresponding JSON schema (assuming PersonArray is the file name):
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Some description",
"type" : "object",
"properties" : {
"persons" : {
"type" : "array",
"items" : { "$ref": "#/definitions/person" }
}
},
"definitions": {
"person" : {
"type": "object",
"description": "A person",
"properties": {
"name": { "type": "string" }
}
}
}
}
and take advantage of Jackson Data Binding API by using jsonschema2pojo-maven-plugin Maven plugin to generate POJOs in Java (alternatively, you can manually implement POJOs).
Once POJOs are generated, you can use ObjectMapper to deserialise JSON document in the following way:
ObjectMapper mapper = new ObjectMapper();
PersonArray personArray = mapper.readValue(serialisedJsonDocument, PersonArray.class);
The elements of your JSON document will be stored inside PersonArray object as:
List<Person> persons = new ArrayList<Person>();
You could also add additional properties to the Person object if you needed.

Nested JSON Request with Volley -> Escaped chars

I want to make a post request with volley to a REST API.
Therefore, I create a JSONObject and put a JSON String generated from a class in it.
JSONObject jsonObject = new JSONObject();
String json = gson.toJson(MyClazz);
try {
jsonObject.put(PARAM, json);
}
catch (JSONException e1) {
e1.printStackTrace();
}
The problem is that the correct calculated JSON String gets escaped and can't be recognized on the back end.
So toJson() gives something like:
{
"device_identifier":"324234234",
"name":"NameMe",
"list":[
{"prop":"A","prop2":-10},
{"prop":"B","prop2":-12}
]
}
The jsonObject's output is like
{
"PARAM":{
\"device_identifier\":\"324234234\",
\"name\":\"NameMe\",
\"list\":[
{\"prop\":\"A\",\"prop2\":-10},
{\"prop\":\"B\","\prop2\":-12}
]
}
}
I need the PARAM for the JSON structure so I can't give it directly to the REST-API. Any ideas how I can avoid the additional escaping?
You could wrap your MyClazz object with a simple wrapper object, and then pass that wrapped object to Gson's toJson method.
Given this class based on your example JSON,
public class MyClazz {
public String device_identifier;
public String name;
public List<Prop> list;
public class Prop {
public String prop;
public Integer prop2;
}
}
here's a possible wrapper implementation. Note the use of com.google.gson.annotations.SerializedName which tells Gson to use the PARAM key in the JSON representation.
public class MyClazzWrapper {
public MyClazzWrapper(MyClazz myClazz) {
this.myClazz = myClazz;
}
#SerializedName("PARAM")
private MyClazz myClazz;
}
And here's an example using it:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
MyClazz myClazz = gson.fromJson("{\"device_identifier\":\"324234234\",\"name\":\"NameMe\",\"list\":[{\"prop\":\"A\",\"prop2\":-10},{\"prop\":\"B\",\"prop2\":-12}]}", MyClazz.class);
MyClazzWrapper wrapped = new MyClazzWrapper(myClazz);
System.out.println(gson.toJson(wrapped));
The above will print:
{
"PARAM": {
"device_identifier": "324234234",
"name": "NameMe",
"list": [
{
"prop": "A",
"prop2": -10
},
{
"prop": "B",
"prop2": -12
}
]
}
}

Categories