I have a bunch of JSON objects in a string notation:
"{\"address\":{\"street\":\"Steenstraat\",\"housenumber\":\"17A\",\"postalcode\":\"6828 CA\",\"city\":\"ARNHEM\",\"geoLocation\":{\"lat\":\"51.983718\",\"lng\":\"5.915553\"}},\"distance\":0,\"type\":\"ING\"}
So each of the JSON object looks something like this:
{
"address" : {
"street" : "Steenstraat",
"housnumber" : "17A",
"postalcode" : "6828 CA",
"city" : "ARNHEM",
"geolocation" : {
"latitude" : "51.983718",
"longitude" : "54.983718"
}
},
"type" : "citi",
"distance" : 0
}
Now, I used google's gson library to get from the rest API and that has given me a string of many of the above JSON objects. How can I try to filter out (or redefine the structure of the JSON) to sort the JSON objects by a particular parameter (say sort by city names)?
This is my Atm class. I'm trying to convert the JSON string to a list of Atm objects.
public class Atm {
private String type;
private Long distance;
private Map<String, String> address = new HashMap<String, String>();
public Atm() {
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Long getDistance() {
return distance;
}
public void setDistance(Long distance) {
this.distance = distance;
}
public Map<String, String> getAddress() {
return address;
}
public void setAddress(Map<String, String> address) {
this.address = address;
}
#Override
public String toString() {
return "Atm{" +
"type='" + type +
", distance=" + distance +
", address=" + address.toString() +
'}';
}
}
Or is there a way to do this without converting it into java data structures?
Note: As you are using a subelement geoLocation in your JSON, you cannot use Map<String, String>.
You should use: Map<String, Object> instead or create a custom class to represent your address.
To filter your Atm list by city you could do the following.
In Java 8:
Gson gson = new Gson();
String atm1 = "{\"address\":{\"street\":\"Steenstraat\",\"housenumber\":\"17A\",\"postalcode\":\"6828 CA\",\"city\":\"ARNHEM\",\"geoLocation\":{\"lat\":\"51.983718\",\"lng\":\"5.915553\"}},\"distance\":0,\"type\":\"ING\"}";
String atm2 = "{\"address\":{\"street\":\"Steenstraat\",\"housenumber\":\"17A\",\"postalcode\":\"6828 CA\",\"city\":\"ARNHEM\",\"geoLocation\":{\"lat\":\"51.983718\",\"lng\":\"5.915553\"}},\"distance\":0,\"type\":\"ING\"}";
String atm3 = "{\"address\":{\"street\":\"Steenstraat\",\"housenumber\":\"17A\",\"postalcode\":\"6828 CA\",\"city\":\"NEW-YORK\",\"geoLocation\":{\"lat\":\"51.983718\",\"lng\":\"5.915553\"}},\"distance\":0,\"type\":\"ING\"}";
List<Atm> atms = new ArrayList<Atm>();
atms.add(gson.fromJson(atm1, Atm.class));
atms.add(gson.fromJson(atm2, Atm.class));
atms.add(gson.fromJson(atm3, Atm.class));
List<Atm> filteredOnCity = atms.stream().filter(atm -> atm.getAddress().get("city")
.equals("ARNHEM")).collect(Collectors.toList());
With Apache commons-collections4:
//Build your list with code from above
Predicate<Atm> filterOnCity = new Predicate<Atm>() {
#Override
public boolean evaluate(Atm atm) {
return atm.getAddress().get("city").equals("ARNHEM");
}
};
CollectionUtils.filter(atms, filterOnCity);
Why not filter or sort them on the client side before sending them to the Java?
var arr = JSON.parse(MY_JSON_ARRAY_STRING);
arr.sort(function(a, b){
if ( a.city < b.city )
return -1;
if ( a.city > b.city )
return 1;
return 0;
});
var arrString = JSON.stringify(arr);
Related
This is my 1st java project.
I m using a 3rd party Flight API in Java.
Actually the issue is, if the data received only has 1 record, I get data in Object format and if data received has more than 1 record, I get data in Array format. Now the issue is, I created a POJO class in which I defined it as Array but when i get data in Object format, It gives error :
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1
public class MlFlightGetFlightAvailibilityResponse {
private MlAirlineList[] AirlineList;
public MlAirlineList[] getAirlineList() {
return AirlineList;
}
public void setAirlineList(MlAirlineList[] AirlineList) {
this.AirlineList = AirlineList;
}
#Override
public String toString() {
return "ClassPojo [AirlineList = " + AirlineList + "]";
}
}
public class MlAirlineList {
private String AirlineCode;
private String AirlineName;
public MlAirlineList(String AirlineCode, String AirlineName) {
this.AirlineCode = AirlineCode;
this.AirlineName = AirlineName;
}
public String getAirlineCode() {
return AirlineCode;
}
public void setAirlineCode(String AirlineCode) {
this.AirlineCode = AirlineCode;
}
public String getAirlineName() {
return AirlineName;
}
public void setAirlineName(String AirlineName) {
this.AirlineName = AirlineName;
}
#Override
public String toString() {
return "ClassPojo [AirlineCode = " + AirlineCode + ", AirlineName = " + AirlineName + "]";
}
}
Below is the for loop in which i get error
Map<String, String> mlFlightAirline = new HashMap<>(); // Unique Flight Airline List
Gson gson = new Gson();
MlFlightResponse mlflights = gson.fromJson(mlResponse, MlFlightResponse.class); // mlResponse is JSON response
public class MlFlightResponse {
private MlFlightGetFlightAvailibilityResponse GetFlightAvailibilityResponse;
public MlFlightGetFlightAvailibilityResponse getGetFlightAvailibilityResponse() {
return GetFlightAvailibilityResponse;
}
public void setGetFlightAvailibilityResponse(MlFlightGetFlightAvailibilityResponse GetFlightAvailibilityResponse) {
this.GetFlightAvailibilityResponse = GetFlightAvailibilityResponse;
}
#Override
public String toString() {
return "ClassPojo [GetFlightAvailibilityResponse = " + GetFlightAvailibilityResponse + "]";
}
}
for (MlAirlineList airline : mlflights.getGetFlightAvailibilityResponse().getAirlineList()) {
mlFlightAirline.put(airline.getAirlineCode(), airline.getAirlineName());
}
In Above code, MlAirlineList sometimes comes as Array and sometimes has Object based on number of records available.
Object Data Format:
{
"AirlineList": {
"AirlineCode":"test",
"AirlineName":"test"
}
}
{
"AirlineList": [{
"AirlineCode":"test",
"AirlineName":"test"
},
{
"AirlineCode":"test",
"AirlineName":"test"
}]
}
Please guide me in right direction.
Thanks
From what I can see you have an Array of Arrays in JSON response you are trying to process.
Try
for (MlAirlineList airline : mlflights.getGetFlightAvailibilityResponse().getAirlineList()) {
mlFlightAirline.put(airline[0], airline[1]);
}
You can put manual check for this for hot-fix.If response start with "{" and ends with "}" then you can add [ and ] into the response in start and end part .this will surely work
I have these JSON String:
{
"Results": {
"output1": {
"type": "table",
"value": {
"ColumnNames": ["userId", "documentId", "Scored Labels", "Scored Probabilities"],
"ColumnTypes": ["String", "String", "Boolean", "Double"],
"Values": [["100213199594809000000", "1Ktol-SWvAh8pnHG2O7HdPrfbEVZWX3Vf2YIPYXA_8gI", "False", "0.375048756599426"], ["103097844766994000000", "1jYsTPJH8gaIiATix9x34Ekcj31ifJMkPNb0RmxnuGxs", "True", "0.753859758377075"]]
}
}
}
}
And I want to have only the ColumnNames and the Values. I have tried it with something like this:
Map<String,Object> map = mapper.readValue(filename, Map.class);
String CN = (String) map.get("ColumnNames");
But then I get the following error:
Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('A' (code 65)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.StringReader#64232b15; line: 1, column: 2]`
I've worked only few times with JSON. Can anybody help me here?
The best case for me would be something like this, which I've done in another case:
String uId = (String) attr.get("userId");
Is it possible?
So now I've done this:
I try it like this:
public class ClientPOJO {
private String userId;
private String documentId;
public String getuserId() {
return userId;
}
public void setuserId(String userId) {
this.userId = userId;
}
public String getdocumentId() {
return documentId;
}
public void setdocumentId(String documentId) {
this.documentId = documentId;
}
}
and then:
ObjectMapper mapper = new ObjectMapper();
ClientPOJO clientes= mapper.readValue(filename, ClientPOJO.class);
String uid = clientes.getuserId();
But now when I make a Prtinout I'll get the same error like before:
Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('A' (code 65)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.StringReader#7a6eb29d; line: 1, column: 2]
Java- Convert JSON string into string / integer / Object
String jsonString = "{"username":"Gajender"}";
org.json.JSONObject jsonObj =new JSONObject(jsonString);
String name = (String) jsonObj.get("username").toString();
Below is an example to illustrate a generic approach to solve your problem ( based on Jackson library). You may like to enhance the solution to meet your all requirements.
Comments inlined.
package com.stackoverflow;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
// Junit class
public class TableDeserExample {
// sample input
String inputJson = "{\n" +
" \"Results\": {\n" +
" \"output1\": {\n" +
" \"type\": \"table\",\n" +
" \"value\": {\n" +
" \"ColumnNames\": [\"userId\", \"documentId\", \"Scored Labels\", \"Scored Probabilities\"],\n" +
" \"ColumnTypes\": [\"String\", \"String\", \"Boolean\", \"Double\"],\n" +
" \"Values\": [[\"100213199594809000000\", \"1Ktol-SWvAh8pnHG2O7HdPrfbEVZWX3Vf2YIPYXA_8gI\", \"False\", \"0.375048756599426\"], [\"103097844766994000000\", \"1jYsTPJH8gaIiATix9x34Ekcj31ifJMkPNb0RmxnuGxs\", \"True\", \"0.753859758377075\"]]\n"
+
" }\n" +
" }\n" +
" }\n" +
"}";
// POJO to map the Json structure. You may want to make it generalize based
// on field "type"
// (https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization)
public static class Result {
private String type;
private TableResult value;
public String getType() {
return this.type;
}
public void setType(String type) {
this.type = type;
}
public void setValue(TableResult value) {
this.value = value;
}
public TableResult getValue() {
return this.value;
}
}
// Pojo for table result
public static class TableResult {
private List<String> columnNames;
private List<String> columnTypes;
private List<Object[]> values;
#JsonProperty("ColumnNames")
public List<String> getColumnNames() {
return this.columnNames;
}
public void setColumnNames(List<String> columnNames) {
this.columnNames = columnNames;
}
#JsonProperty("ColumnTypes")
public List<String> getColumnTypes() {
return this.columnTypes;
}
public void setColumnTypes(List<String> columnTypes) {
this.columnTypes = columnTypes;
}
#JsonProperty("Values")
public List<Object[]> getValues() {
return this.values;
}
public void setValues(List<Object[]> values) {
this.values = values;
}
}
// Top level Json POJO
public static class ResultContainer {
private Map<String, Result> results;
#JsonProperty("Results")
public Map<String, Result> getResults() {
return this.results;
}
public void setResults(Map<String, Result> results) {
this.results = results;
}
}
// A contract to map the result "values" to the expected object
public static interface ResultMapper<T> {
T map(TableResult map, Object[] row);
}
// Basic implementation for mapping user object from json "values[i]" array
public static class UserTableResultMapper implements ResultMapper<User> {
#Override
public User map(TableResult result, Object[] row) {
User user = new User();
// Here use any mapper logic based on column name
// Retrieved from result object.
// Below are for illustration only
user.setId(String.valueOf(row[0]));
user.setDocumentId(String.valueOf(row[1]));
return user;
}
}
// A result reader class
public static class ResultReader<T> implements Iterable<T> {
private TableResult result;
private ResultMapper<T> mapper;
public ResultReader(TableResult result, ResultMapper<T> mapper) {
this.result = result;
this.mapper = mapper;
}
#Override
public Iterator<T> iterator() {
final Iterator<Object[]> itr = result.getValues().iterator();
return new Iterator<T>() {
#Override
public void remove() {
throw new UnsupportedOperationException();
}
#Override
public T next() {
Object[] values = itr.next();
return mapper.map(result, values);
}
#Override
public boolean hasNext() {
return itr.hasNext();
}
};
};
}
public static class User {
private String id;
private String documentId;
// and others
public String getId() {
return this.id;
}
public void setDocumentId(String documentId) {
this.documentId = documentId;
}
public void setId(String id) {
this.id = id;
}
public String getDocumentId() {
return this.documentId;
}
}
#Test
public void simpleTest() throws Exception {
ObjectMapper mapper = new ObjectMapper();
ResultContainer file = mapper.readValue(inputJson, ResultContainer.class);
Result result = file.getResults().get("output1");
ResultReader<User> userResultReader = new ResultReader<>(result.getValue(), new UserTableResultMapper());
for (User user : userResultReader) {
System.out.println(user.getId() + " : " + user.getDocumentId());
}
}
}
If you know exactly the structure of your json (like the json you have post) then you can using Gson to get your object like this:
JsonParser parser = new JsonParser();
JsonObject json = (JsonObject) parser.parse("your_json_string_here");
String column = json.get("Results").getAsJsonObject().get("output1").getAsJsonObject().get("value").getAsJsonObject().get("ColumnNames").getAsJsonArray().toString();
String value = json.get("Results").getAsJsonObject().get("output1").getAsJsonObject().get("value").getAsJsonObject().get("Values").getAsJsonArray().toString();
System.out.println(column);
System.out.println(value);
If you need some things more generic then you can parse your json string to a HashMap<String, Object> then using recursion to read the HashMap and get the value you want.
Example (in my code, the type of Map will corresponding to a Json Object, type of List will corresponding to the Array in Json string):
Type type = new TypeToken<HashMap<String, Object>>() {}.getType();
Gson gson = new Gson();
HashMap<String, Object> map = gson.fromJson("your_json_string_here", type);
for (String key : map.keySet()) {
Object obj = map.get(key);
if (obj instanceof List) {
for (Object o : (List) obj) {
if (o instanceof Map) {
loop((Map) o);
} else {
System.out.println(key + " : " + o);
}
}
} else if (obj instanceof Map) {
loop((Map) obj);
} else {
System.out.println(key + " : " + obj);
}
}
}
private static void loop(Map<String, Object> map) {
for (String key : map.keySet()) {
Object obj = map.get(key);
if (obj instanceof List) {
for (Object o : (List) obj) {
if (o instanceof Map) {
loop((Map) o);
} else {
System.out.println(key + " : " + o);
}
}
} else if (obj instanceof Map) {
loop((Map) obj);
} else {
System.out.println(key + " : " + obj);
}
}
}
Neither Jackson nor any other library will parse the Values array into objects with client data like your POJO. You can achieve this by getting the raw tree of data in this JSON and constructing objects by iterating over the Values array inside this tree. Assuming the order of ColumnNames is fixed then you can parse with Jackson like this:
final ObjectMapper mapper = new ObjectMapper();
final JsonNode tree = mapper.readTree(json);
final JsonNode values = tree.findValue("Values");
final List<ClientPOJO> clients = new ArrayList<>();
for (JsonNode node : values) {
final ClientPOJO client = new ClientPOJO();
client.setUserId(node.get(0).asText());
client.setDocumentId(node.get(1).asText());
client.setScoredLabels(node.get(2).asBoolean());
client.setScoredProbabilities(node.get(3).asDouble());
clients.add(client);
}
Docs for JsonNode. Basically with findValue you can get another node deep into the tree, with get you can get array elements by index and with asText etc you parse a value in JSON into the appropriate type in Java.
Since you seem to be flexible in choice of JSON parsing library I would suggest Jackson 2 from com.fasterxml instead of Jackson 1 from org.codehaus that you tried.
This Json
{
"age":"23",
"name":"srinivas",
"blog":"A",
"messages":["msg1","msg2","msg3"]
}
I want convert a json to java class like this class and class use:
public class A
{
private String name;
private String age;
private String blog;
private String[] messages;
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public String getAge ()
{
return age;
}
public void setAge (String age)
{
this.age = age;
}
public String getBlog ()
{
return blog;
}
public void setBlog (String blog)
{
this.blog = blog;
}
}
No. You cant have class created automatically for you from your json.
However the below thing you might be needing that's related:
You need link
Excerpt from the link, below example code:
String carJson =
"{ \"brand\" : \"Mercedes\", \"doors\" : 5," +
" \"owners\" : [\"John\", \"Jack\", \"Jill\"]," +
" \"nestedObject\" : { \"field\" : \"value\" } }";
ObjectMapper objectMapper = new ObjectMapper();
try {
JsonNode node = objectMapper.readValue(carJson, JsonNode.class);
JsonNode brandNode = node.get("brand");
String brand = brandNode.asText();
System.out.println("brand = " + brand);
JsonNode doorsNode = node.get("doors");
int doors = doorsNode.asInt();
System.out.println("doors = " + doors);
JsonNode array = node.get("owners");
JsonNode jsonNode = array.get(0);
String john = jsonNode.asText();
System.out.println("john = " + john);
JsonNode child = node.get("nestedObject");
JsonNode childField = child.get("field");
String field = childField.asText();
System.out.println("field = " + field);
} catch (IOException e) {
e.printStackTrace();
}
You technically can create a class at runtime: see How to create a class dynamically in java or Creating classes dynamically with Java. However, if your code wants to use A in some way, it needs to be available during compilation. And if your code doesn't need to use A, why create it? You could implement some interface/extend some class which is available during compilation, but in your case there is no reasonable common interface and you could only access it using reflection.
A more reasonable alternative would be to generate a class from known JSON examples (or better, from some schema description) during your build process. Again, there are many ways to do this and you should search for one which fits your needs.
I have my original JSON String like this in which I have key and value as shown below -
{
"u":{
"string":"1235"
},
"p":"2047935",
"client_id":{
"string":"5"
},
"origin":null,
"item_condition":null,
"country_id":{
"int":3
},
"timestamp":{
"long":1417823759555
},
"impression_id":{
"string":"2345HH*"
},
"is_consumerid":true,
"is_pid":false
}
As an example, one key is "u" and its value is -
{
"string":"1235"
}
Similarly another key is "country_id" and its value is -
{
"int":3
}
Now what I need to do is, I need to represent key value pair as shown below. If any value is string data type (like value for key u), then represent it's value in double quotes, otherwise don't represent it's value in double quotes. Meaning value of country_id won't be in String double quotes since it is an int.
"u": "1235"
"p": "2047935"
"client_id": "5"
"origin":null
"item_condition":null
"country_id": 3 // I don't have double quotes here around 3 since country_id was int that's why
"timestamp": 1417823759555
"impression_id": "2345HH*"
"is_consumerid": true
"is_pid": false
And then I need to make another json string which should look like this -
{
"u": "1235",
"p": "2047935",
"client_id": "5",
"origin":null,
"item_condition":null,
"country_id": 3,
"timestamp": 1417823759555,
"impression_id": "2345HH*",
"is_consumerid": true,
"is_pid": false
}
So I started with below code but not able to understand what should I do further?
String response = "original_json_string";
Type type = new TypeToken<Map<String, Object>>() {}.getType();
JsonObject jsonObject = new JsonParser().parse(response).getAsJsonObject();
for (Map.Entry<String, JsonElement> object : jsonObject.entrySet()) {
if (object.getValue() instanceof JsonObject) {
String data = object.getValue().toString();
// now not sure what should I do here?
}
}
And my new json should print out like this after serializing.
{
"u": "1235",
"p": "2047935",
"client_id": "5",
"origin":null,
"item_condition":null,
"country_id": 3,
"timestamp": 1417823759555,
"impression_id": "2345HH*",
"is_consumerid": true,
"is_pid": false
}
What is the best way to achieve this?
Note that I'm not yet very experienced with Gson, so there might be easiest ways to do it. Also this solution comes up after the discussion we had previously.
Basically the problem was to get the wanted type in the json file back (which is done by the addEntry method) and each #event key should have its own JSON string (done by computeJson). Since there are only two nested levels, it's fine to do it like that. Otherwise a recursive approach will do the trick.
So if you have only one nested level, you should iterate other the JsonObject's entries'. For each entries, computeJson will add a new Json entry in the List which corresponds to each #event key.
public class Test {
public static void main(String[] args) throws Exception {
List<String> output = new ArrayList<>();
JsonObject jsonObject = new JsonParser().parse(new FileReader("myJson.json")).getAsJsonObject();
for (Map.Entry<String, JsonElement> object : jsonObject.entrySet()) {
if (object.getValue() instanceof JsonObject) {
output.add(computeJson((JsonObject)object.getValue()));
}
}
System.out.println(output);
}
private static String computeJson(JsonObject source) {
JsonObject output = new JsonObject();
for (Map.Entry<String, JsonElement> object : source.entrySet()) {
if (object.getValue() instanceof JsonObject) {
for(Map.Entry<String, JsonElement> entry : ((JsonObject)object.getValue()).entrySet()) {
addEntry(object.getKey(), output, entry);
}
} else {
addEntry(object.getKey(), output, object);
}
}
Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
return gson.toJson(output);
}
private static void addEntry(String key, JsonObject output, Map.Entry<String, JsonElement> object) {
switch(object.getKey().toLowerCase()) {
case "string":
output.addProperty(key, object.getValue().getAsString());
break;
case "int":
output.addProperty(key, object.getValue().getAsInt());
break;
case "long":
output.addProperty(key, object.getValue().getAsLong());
break;
//add other primitive cases
default:
output.add(key, object.getValue());
}
}
}
As described here RawCollectionsExample you can manually parse the json and set it in the desired object. Once values are parsed and set you can again serialize the java object to have desired json.
For setting values from your json you need to have POJO shown below.
public class CustomObject {
private String u;
private String p;
private String client_id;
private String origin;
private String item_condition;
private int country_id;
private long timestamp;
private String impression_id;
private boolean is_consumerid;
private boolean is_pid;
public String getU() {
return u;
}
public void setU(String u) {
this.u = u;
}
public String getP() {
return p;
}
public void setP(String p) {
this.p = p;
}
public String getClient_id() {
return client_id;
}
public void setClient_id(String clientId) {
client_id = clientId;
}
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public String getItem_condition() {
return item_condition;
}
public void setItem_condition(String itemCondition) {
item_condition = itemCondition;
}
public int getCountry_id() {
return country_id;
}
public void setCountry_id(int countryId) {
country_id = countryId;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getImpression_id() {
return impression_id;
}
public void setImpression_id(String impressionId) {
impression_id = impressionId;
}
public boolean isIs_consumerid() {
return is_consumerid;
}
public void setIs_consumerid(boolean isConsumerid) {
is_consumerid = isConsumerid;
}
public boolean isIs_pid() {
return is_pid;
}
public void setIs_pid(boolean isPid) {
is_pid = isPid;
}
#Override
public String toString() {
return "CustomObject [client_id=" + client_id + ", country_id="
+ country_id + ", impression_id=" + impression_id
+ ", is_consumerid=" + is_consumerid + ", is_pid=" + is_pid
+ ", item_condition=" + item_condition + ", origin=" + origin
+ ", p=" + p + ", timestamp=" + timestamp + ", u=" + u + "]";
}
}
In above POJO you can parse and set JSON value manually as shown below :
String jsonLine = "{ \"u\":{ \"string\":\"1235\" }, \"p\":\"2047935\", \"client_id\":{ \"string\":\"5\" }, \"origin\":null, \"item_condition\":null, \"country_id\":{ \"int\":3 }, \"timestamp\":{ \"long\":1417823759555 }, \"impression_id\":{ \"string\":\"2345HH*\" }, \"is_consumerid\":true, \"is_pid\":false}";
JsonParser parser = new JsonParser();
//in case you have json array you need to use .getAsJsonArray instead of getAsJsonObject
JsonObject jsonObject = parser.parse(jsonLine).getAsJsonObject();
CustomObject obj = new CustomObject();
obj.setP(jsonObject.get("p").getAsString());
obj.setU(jsonObject.get("u").getAsJsonObject().get("string").getAsString());
obj.setClient_id(jsonObject.get("client_id").getAsJsonObject().get("string").getAsString());
//null check which will be required for each value in case there are possibility of having null values
String origin = jsonObject.get("origin").isJsonNull() ==true?null:jsonObject.get("origin").getAsString();
obj.setOrigin(origin);
String itemCondition = jsonObject.get("item_condition").isJsonNull() ==true?null:jsonObject.get("item_condition").getAsString();
obj.setItem_condition(itemCondition);
obj.setCountry_id(jsonObject.get("country_id").getAsJsonObject().get("int").getAsInt());
obj.setTimestamp(jsonObject.get("timestamp").getAsJsonObject().get("long").getAsLong());
obj.setImpression_id(jsonObject.get("impression_id").getAsJsonObject().get("string").getAsString());
obj.setIs_consumerid(jsonObject.get("is_consumerid").getAsBoolean());
obj.setIs_pid(jsonObject.get("is_consumerid").getAsBoolean());
System.out.println("JSON OUTPUT "+ new Gson().toJson(obj));
You can run the code snippet in any class's main method to validate. Check the last line above which outputs required json. Let me know if this is not what you were looking for.
I have a JSON response that I try to parse with Jackson, and type of one of fields is unknown.
Exapmle:
{"name" : "Catalina"}
OR
{"name" : {"First" : "Catalina", "Last" : "Kyle"}}
How I can deserialize that object into POJO:
class NamesHolder {
public String singleName;
public Map<String, String> nameMap;
}
This is synthetic example but I hope it clear for understanding.
In first case I want to have object with singleName == "Catalina" and nameMap == null, and vice versa in other case.
UPDATE
I am really sorry, at the end of day I misspelled the property name. In both cases they are the same: name.
Try making your name field an object:
class MyPojo {
public Object name;
}
The you'll have to check at runtime to see if it deserialized as a String or as a Map.
The easiest way is to rename your POJO properties to the same which you have in JSON. See below example:
class NamesHolder {
public String name;
public Map<String, String> names;
#Override
public String toString() {
return "NamesHolder{" +
"name='" + name + '\'' +
", names=" + names +
'}';
}
}
If you do not want to rename properties you can use #JsonProperty annotation. See below example:
class NamesHolder {
#JsonProperty("name")
public String singleName;
#JsonProperty("names")
public Map<String, String> nameMap;
#Override
public String toString() {
return "NamesHolder{" +
"name='" + singleName + '\'' +
", names=" + nameMap +
'}';
}
}
Two above classes work for your JSON examples. See below program:
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue("{\"names\" : {\"First\" : \"Catalina\", \"Last\" : \"Kyle\"}}", NamesHolder.class));
System.out.println(mapper.readValue("{\"name\" : \"Catalina\"}", NamesHolder.class));
which prints:
NamesHolder{name='null', names={First=Catalina, Last=Kyle}}
NamesHolder{name='Catalina', names=null}
EDIT 1
In this case you have to handle it manually using Object type. See below example:
public class JacksonTest {
public static void main(String[] args) throws Exception {
String json = "{\"name\" : \"Catalina\"}";
ObjectMapper deserializerMapper = new ObjectMapper();
NamesHolder namesHolder = deserializerMapper.readValue(json, NamesHolder.class);
System.out.println(toString(namesHolder));
json = "{\"name\" : {\"First\" : \"Catalina\", \"Last\" : \"Kyle\"}}";
namesHolder = deserializerMapper.readValue(json, NamesHolder.class);
System.out.println(toString(namesHolder));
}
private static String toString(NamesHolder namesHolder) {
if (namesHolder.hasStringName()) {
return "Type: String, Value: " + namesHolder.getStringName();
} else if (namesHolder.hasMapNames()) {
return "Type: Map, Value: " + namesHolder.getMapNames();
}
return "Type: Unknown, Value: " + namesHolder;
}
}
class NamesHolder {
public Object name;
public boolean hasStringName() {
return name instanceof String;
}
public String getStringName() {
return name.toString();
}
public boolean hasMapNames() {
return name instanceof Map;
}
public Map<String, String> getMapNames() {
return (Map<String, String>) name;
}
#Override
public String toString() {
return String.valueOf(name);
}
}
Above example prints:
Type: String, Value: Catalina
Type: Map, Value: {First=Catalina, Last=Kyle}