JSON parsing using Gson - java

I am trying to parse a JSON object using GSON.
My JSON is :
{ "truncate": [
{
"lower": 20,
"upper": 40,
"delimiter": " ",
"scope": ["$title"]
},
{
"lower": 30,
"upper": 65,
"delimiter": " "
}
] }
I have defined my 2 classes like:
public class TruncateObj {
private List<TruncateObjectChild> objChild;
// getter and setter
}
and
public class TruncateObjectChild {
private int lower;
private int upper;
private String delimiter;
private List<String> scope;
// getters and setters
}
My Parsing statement is
Gson gson = new Gson();
TruncateObj truncation = gson.fromJson(template, TruncateObj.class);
For some reason this is not working. Gson creates a TruncatObj child, but the List<TruncateObjectChild> within the TruncateObj is null.
What is wrong in what I am doing?

The field objChild in your TruncateObj does not match the name it has in the JSON. Rename the field to truncate and try again.
Alternatively, you could annotate the objChild field with an #SerializedName("truncate") to tell gson to use the value from the truncate field in the JSON as the value for the objChild field in your Java object.

Related

How to convert an json response like that?

I have a json reponse like given below.Basically,I want to convert an object and use it.
[
{
"Id": 1290,
"N": "Türkiye",
"Fid": 196,
"EC": 10,
"CL": null,
"SID": 0
},
{
"Id": 1239,
"N": "Dünya",
"Fid": 152,
"EC": 63,
"CL": null,
"SID": 0
}
]
... Goes on
Here is what I have tried,I am using org.json library.
String jsonString = response.body().string(); // Getting json response and converting to string.
JSONObject jsonResponse = new JSONObject( jsonString ); // Not working
JSONArray jsonArray = new JSONArray( jsonString ); // Not working
JSONArray matches = new JSONArray( jsonString ).getJSONArray(0); // Not working
But I am gettin those errors
A JSONObject text must begin with '{' at 0 [character 1 line 1]
A JSONArray text must begin with '{' at 0 [character 1 line 1]
I have checked topics like Parse JSON Array without Key. But the json described not like mine.
Any idea what should ı do?
in Java you would first need to define a class which has all the attributes
public class MyClass {
private int Id;
private int N;
private int Fid;
private int EC;
private int CL;
private int Sid;
// getters, setters, no arg constructor
}
then you can use for example gson library to parse it like this:
MyClass[] myClassArray = gson.fromJson(jsonString , MyClass[].class)
I really recommend you to use the Gson library it's way better to perform data operations:
public class User {
int id;
String n;
int fid;
int ec;
String cl;
int sid;
public static User[] parse(String s){
return new GsonBuilder().create().fromJson(s, User[].class);
}
}
Have you looked into Google's Gson? It is really easy to use and you can both serialize and deserialize objects.
Here is an example:
public Company[] deserializeCompany() {
Gson gson = new Gson();
Company[] companies = gson.fromJson(companiesJSON, Company[].class);
return companies;
}
First you need to make a template class that has a member field for each key in the json. E.g. private String id for the 'Id' key in the json you provided. In my example it is the Company class.
Next you make a new Gson object using Gson gson = new Gson(); and use the .fromJson function supplying it both the Json array and the Object array type (which is of the form MyClass[].class).
First, your question is not to convert a JSON array without key. Second, there are many popular JSON libraries can achieve what you want such as org.json, Jackson, Gson and so on.
Here comes several examples:
With org.json, you can retrieve field values in a JSON array as follows:
JSONArray jsonResponse = new JSONArray(jsonStr);
System.out.println(jsonResponse.get(0).toString());
System.out.println("Id: " + jsonResponse.getJSONObject(0).get("Id"));
System.out.println("N : " + jsonResponse.getJSONObject(0).get("N"));
And the expected output should be:
{"Fid":196,"CL":null,"Id":1290,"N":"Türkiye","EC":10,"SID":0}
Id: 1290
N : Türkiye
With Jackson, you can retrieve field values in a JSON array as follows:
ObjectMapper objectMapper = new ObjectMapper();
List<Map<String, Object>> jsonResponse = objectMapper.readValue(jsonStr, new TypeReference<List<Map<String, Object>>>() {});
System.out.println(jsonResponse.toString());
System.out.println("Id: " + jsonResponse.get(0).get("Id"));
System.out.println("N : " + jsonResponse.get(0).get("N"));
And the expected output should be:
{Id=1290, N=Türkiye, Fid=196, EC=10, CL=null, SID=0}
Id: 1290
N : Türkiye
3. Furthermore, if you define a POJO as follows:
class MyObject {
private #JsonProperty("Id") int id;
private #JsonProperty("N") String n;
private #JsonProperty("Fid") int fid;
private #JsonProperty("EC") int ec;
private #JsonProperty("CL") int cl;
private #JsonProperty("SID") int sid;
//general getters, setters and toString
}
Then you can deserialize the JSON response to your POJO by:
ObjectMapper objectMapper = new ObjectMapper();
List<MyObject> jsonResponse = objectMapper.readValue(jsonStr, new TypeReference<List<MyObject>>() {});
System.out.println(jsonResponse.get(0).toString());
System.out.println("Id: " + jsonResponse.get(0).getId());
System.out.println("N : " + jsonResponse.get(0).getN());
And the expected output should be:
MyObject{id=1290, n='Türkiye', fid=196, ec=10, cl=0, sid=0}
Id: 1290
N : Türkiye

How can I convert each integer/double value to String from JSON data containing nested objects and arrays?

I want to convert each integer/double value to String present in json request before storing in MongoDB database.
There can be multiple fields like amountValue in the json. I am looking for a generic way which can parse json with any number of such attributes value to string. My request will have around 200 fields.
ex: "amountValue": 200.00, to "amountValue": "200.00",
{
"templateName": "My DC Template 14",
"templateDetails": {
"beneficiaryName": "Snow2",
"dcOpenAmount": {
"amountValue": 200.00,
}
}
}
My mongoDB Document is of the form
#Document
public class TemplateDetails {
#Id
private long templateId;
private String templateName;
private Object templateDetail;
}
Because we are storing document in mongodb as an object(Which can accept any type of json request) we dont have field level control on it.
In my controller, converting the request object to json.
This is how I tried. But its not meeting my expectation. It is still keeping the amount value to its original double form.:
ObjectMapper mapper = new ObjectMapper();
try {
String json = mapper.writeValueAsString(templateRequestVO);
System.out.println("ResultingJSONstring = " + json);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
Output :
ResultingJSONstring = {"id":null,"userId":"FU.ZONKO","txnType":"LCI","accessIndicator":"Public","templateId":null,"templateName":"My DC Template 14","tags":null,"templateDetails":{"applicantDetail":{"applicantName":"Tom","applicantAddress":{"addressLine1":"Infosys, Phase 2","city":"PUNE","state":"MAHARASHTRA","country":"INDIA","zip":"40039"},"accountId":"Account1234","customerId":"JPMORGAN"},"beneficiaryName":"Snow2","dcOpenAmount":{"amountValue":200.0,"currency":"USD"}}}
Is there any way to accomplish the result ? Or anything which can help to store documents in mongodb with attribute type as String ?
You can use Json manipulation avaliable in "org.json.JSONObject" to convert Double value to Stirng .
If your Json structure won't change and will remain as said above , you can do the following.
import org.json.JSONObject;
public static void main(String args[]) {
String j = "{ \"templateName\": \"My DC Template 14\", \"templateDetails\": { \"beneficiaryName\": \"Snow2\", \"dcOpenAmount\": { \"amountValue\": 200.00 } } }";
JSONObject jo = new JSONObject(j);
jo.getJSONObject("templateDetails")
.getJSONObject("dcOpenAmount")
.put("amountValue", String.valueOf(jo.getJSONObject("templateDetails").getJSONObject("dcOpenAmount").getDouble("amountValue")));
System.out.println(jo.toString());
}
Following will be the output
{"templateDetails":{"dcOpenAmount":{"amountValue":"200.0"},"beneficiaryName":"Snow2"},"templateName":"My DC Template 14"}
I don't know for mongodb but for a json string you can replace them with a regex and the function replace like this :
public class Test {
public static void main(String[] args) {
String json = "{\"id\":null,\"userId\":\"FU.ZONKO\",\"txnType\":\"LCI\",\"accessIndicator\":\"Public\",\"templateId\":null,\"templateName\":\"My DC Template 14\",\"tags\":null,\"templateDetails\":{\"applicantDetail\":{\"applicantName\":\"Tom\",\"applicantAddress\":{\"addressLine1\":\"Infosys, Phase 2\",\"city\":\"PUNE\",\"state\":\"MAHARASHTRA\",\"country\":\"INDIA\",\"zip\":\"40039\"},\"accountId\":\"Account1234\",\"customerId\":\"JPMORGAN\"},\"beneficiaryName\":\"Snow2\",\"dcOpenAmount\":{\"amountValue\":200.0,\"currency\":\"USD\"}}}";
System.out.println(replaceNumberByStrings(json));
}
public static String replaceNumberByStrings(String str){
return str.replaceAll("(?<=:)\\d+(\\.\\d+)?(?=(,|}))","\"$0\"");
}
}
It will look for all fields with a numeric value in the json string and add quotes to the value. This way they will be interpreted as strings when the json willl be parsed.
It will not work if the value is in an array though, but in this case it should not be a problem.

gson de-serialising object array without identifier

Im getting an error trying to take a json array to a list of objects, the exception is as below.
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 170
here is the code i am trying to use
public static void main(String[] args) throws FileNotFoundException {
Gson gson = new Gson();
Test test = new Test();
JsonElement json = gson.fromJson(test.getFile("fieldTypes.json"), JsonElement.class);
String result = gson.toJson(json);
System.out.println(result);
Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();
JiraField[] jiraFields = gson.fromJson(result, listType);
for (JiraField jiraField : jiraFields) {
System.out.println(jiraField);
}
}
This is the file contents
[
{
"id": "issuetype",
"key": "issuetype",
"name": "Issue Type",
"custom": false,
"orderable": true,
"navigable": true,
"searchable": true,
"clauseNames": [
"issuetype",
"type"
],
"schema": {
"type": "issuetype",
"system": "issuetype"
}
},
{
"id": "timespent",
"key": "timespent",
"name": "Time Spent",
"custom": false,
"orderable": false,
"navigable": true,
"searchable": false,
"clauseNames": [
"timespent"
],
"schema": {
"type": "number",
"system": "timespent"
}
}
]
The file is being read from the resources folder but that is working fine and the sysout is correctly showing the json contents. i assume there is something im doing wrong ?
ok, so. turns out to be caused by un mapped fields, this is how i got it working
in the object you add the #Expose annotation for the fields you want
public class JiraField {
#Expose
private String id ;
#Expose private String key ;
#Expose private String name ;
#Expose private boolean custom ;
#Expose private boolean orderable ;
#Expose private boolean navigable ;
#Expose private String[] clauseNames ;
Then when you initialise gson, you do it like this
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
then it works :)
JiraFields{id='issuetype', key='issuetype', name='Issue Type', custom=false, orderable=true, navigable=true, clauseNames=[issuetype, type]}
JiraFields{id='timespent', key='timespent', name='Time Spent', custom=false, orderable=false, navigable=true, clauseNames=[timespent]}
Try this:
Type listType = new TypeToken<ArrayList<JiraField[]>>(){}.getType();
I think we need to specify the JiraField[] in-order to get Array.
I'm assuming you have a minified JSON according to the exception message ...at line 1 column 170.... It would be nice if you provide both exact your exact JSON document and your mapping as well, since the posted formatted JSON now has the layout destroyed. I'm also assuming your mapping is custom and basically something like:
final class JiraField {
#SerializedName("id")
final String id = null;
#SerializedName("key")
final String key = null;
#SerializedName("name")
final String name = null;
#SerializedName("custom")
final boolean isCustom = Boolean.valueOf(false);
#SerializedName("orderable")
final boolean isOrderable = Boolean.valueOf(false);
#SerializedName("navigable")
final boolean isNavigable = Boolean.valueOf(false);
#SerializedName("searchable")
final boolean isSearchable = Boolean.valueOf(false);
#SerializedName("clauseNames")
final List<String> clauseNames = null;
#SerializedName("schema")
final List<String> schema = null;
}
Note the JiraField.schema field type: it's a list. Trying to deserialize a list of JiraFields with the default Gson configuration would result into:
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 170 path $[0].schema
The symptom and the column are exactly the same (however, again, I'm just assyming your JSON file is minified), but note the path $[0].schema you probably missed to post: it says that an array begin token [ is expected (since the field is a List<String>), but was an object begin token {. Changing the field type to a more appropriate arbitrary Map<String, String> or any other custom appropriate POJO would fix it. Partially.
#SerializedName("schema")
final Map<String, String> schema = null;
Why partially? Your type token is bound to an ArrayList, but you're casting the deserialization result to an array JiraField[], therefore you'd get something like this:
Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to [LJiraField;
To fix it, you have to declare your jiraFields variable matching the deserialized value type: it's an array list, but not an array -- these are not the same in Java.
List<JiraField> jiraFields = ...
Another note regarding deserialization is that you don't need an intermediate json object to deserialize from. test.getFile most likely returns a java.io.Reader, so you can pass it directly to deserialize. Summarizing all up, the following should work for you:
// Immutable and thread-safe, can be instantiated once and shared
private static final Gson gson = new Gson();
// Immutable and thread-safe value type, the same story, + List instead of ArrayList - interfaces are usually much better
private static final Type listType = new TypeToken<List<JiraField>>() {
}.getType();
public static void main(final String... args)
throws IOException {
try ( final Reader reader = test.getFile("fieldTypes.json") ) {
final List<JiraField> jiraFields = gson.fromJson(reader, listType);
for ( final JiraField jiraField : jiraFields ) {
System.out.println(jiraField.key + " => " + jiraField.name);
}
}
}
Output:
issuetype => Issue Type
timespent => Time Spent
Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();
ArrayList<JiraField> jiraFields = gson.fromJson(result, listType);
for (JiraField jiraField : jiraFields) {
System.out.println(jiraField);
}
Try This code
Comment this line
Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();
Try with this
JiraField[] jiraFields = gson.fromJson(result, JiraField[].class);

converting java DTO list into JSON object

I have a DTO class like this:
package stbet.model.dto.db;
public class UKDashboardEventDTO implements Serializable{
private Long eventId;
private String meetingCode;
private String meetingName;
private String eventTime;
private String eventCode;
private String settleStatus;
private String category;
//getters and setters here:
#Override
public String toString() {
return "eventList{" + "eventId=" + eventId + ", meetingCode=" + meetingCode + ", meetingName=" + meetingName
+ "eventTime=" + eventTime + ", eventCode=" + eventCode + ", settleStatus=" + settleStatus
+ ", category=" + category + '}';
}
}
and I do some query stuff and create a java List of above DTO type.
for(Event ev : eventList){
dto = new UKDashboardEventDTO();
// some stuff
dto.setEventCode(ev.getEventCode());
dto.setEventId(ev.getId());
dto.setEventTime(ev.getEventTime());
dto.setMeetingName(ev.getMeeting().getMeetingName());
dto.setMeetingCode(ev.getMeeting().getMeetingCode());
eventDTOList.add(dto);
}
Then I add this list into a Hashmap and covert it into a JSON object like this:
Map map = new HashMap();
map.put("eventList",eventDTOList);
now convert into the json:
JSONObject obj = new JSONObject();
try {
obj.put("eventMap", map);
} catch (JSONException ex) {
}
out.println(obj);
out.flush();
out.close();
but when I get this object from client side, I am getting the dto package/object names list when parse or stringify the output instead of the proper dto values I passed from Java. What I get is this:
"{"eventMap":{"eventList":["stbet.model.dto.db.UKDashboardEventDTO#617538bb","stbet.model.dto.db.UKDashboardEventDTO#56dfaef9","stbet.model.dto.db.UKDashboardEventDTO#775889fd","stbet.model.dto.db.UKDashboardEventDTO#55cb7e41","stbet.model.dto.db.UKDashboardEventDTO#22ce0968","stbet.model.dto.db.UKDashboardEventDTO#4cb9cb2"]}}"
can you please let me know how to get the dto values I set from Java to client side json without java package name as above.
Firstly, you're using both JSON and GSON libraries, JSONException exists in JSON one and Expose annotation is in GSON. Please make sure you don't mix them as I won't work as intended.
Secondly, from Expose documentation
An annotation that indicates this member should be exposed for JSON serialization or deserialization.
This annotation has no effect unless you build Gson with a GsonBuilder and invoke GsonBuilder.excludeFieldsWithoutExposeAnnotation() method.
You should Override the toString field on the DTO, to print out all the individual field values.
This toString will be called when you do out.println(obj);
eg.
toString() {
// this method should list out all the attributes.
}
You should be using GSONBuilder to create the gson. Examples:
Gson: How to exclude specific fields from Serialization without annotations
Gson doesn't parse an exposed field
Here is a post on using GSON also
How to expose a method using GSon?
Finally I could fix it with your suggestions #Trynkiewicz Mariusz and #Paul John.
What I did was:
1. remove #Expose annotation
2. overridden the toString(){...} method.
3. remove the map implementation and used a List.
4. used gson.toJson(eventList);
this solved the issue and the output now is like :
[{
"eventId":167804,
"meetingCode":"V5PGB",
"meetingName":"SprintValley",
"eventTime":"15:38:00",
"eventCode":"10:08:00",
"category":"HR"
},
{
"eventId":167805,
"meetingCode":"V5PGB",
"meetingName":"SprintValley",
"eventTime":"15:50:00",
"eventCode":"10:20:00",
"category":"HR"
},..]
Thanks again guys...

How to convert List to a JSON Object using GSON?

I have a List which I need to convert into JSON Object using GSON. My JSON Object has JSON Array in it.
public class DataResponse {
private List<ClientResponse> apps;
// getters and setters
public static class ClientResponse {
private double mean;
private double deviation;
private int code;
private String pack;
private int version;
// getters and setters
}
}
Below is my code in which I need to convert my List to JSON Object which has JSON Array in it -
public void marshal(Object response) {
List<DataResponse.ClientResponse> clientResponse = ((DataResponse) response).getClientResponse();
// now how do I convert clientResponse list to JSON Object which has JSON Array in it using GSON?
// String jsonObject = ??
}
As of now, I only have two items in List - So I need my JSON Object like this -
{
"apps":[
{
"mean":1.2,
"deviation":1.3
"code":100,
"pack":"hello",
"version":1
},
{
"mean":1.5,
"deviation":1.1
"code":200,
"pack":"world",
"version":2
}
]
}
What is the best way to do this?
There is a sample from google gson documentation on how to actually convert the list to json string:
Type listType = new TypeToken<List<String>>() {}.getType();
List<String> target = new LinkedList<String>();
target.add("blah");
Gson gson = new Gson();
String json = gson.toJson(target, listType);
List<String> target2 = gson.fromJson(json, listType);
You need to set the type of list in toJson method and pass the list object to convert it to json string or vice versa.
If response in your marshal method is a DataResponse, then that's what you should be serializing.
Gson gson = new Gson();
gson.toJson(response);
That will give you the JSON output you are looking for.
Assuming you also want to get json in format
{
"apps": [
{
"mean": 1.2,
"deviation": 1.3,
"code": 100,
"pack": "hello",
"version": 1
},
{
"mean": 1.5,
"deviation": 1.1,
"code": 200,
"pack": "world",
"version": 2
}
]
}
instead of
{"apps":[{"mean":1.2,"deviation":1.3,"code":100,"pack":"hello","version":1},{"mean":1.5,"deviation":1.1,"code":200,"pack":"world","version":2}]}
you can use pretty printing. To do so use
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(dataResponse);
Make sure to convert your collection to Array:
Gson().toJson(objectsList.toTypedArray(), Array<CustomObject>::class.java)
We can also use another workaround by first creating an array of myObject then convert them into list.
final Optional<List<MyObject>> sortInput = Optional.ofNullable(jsonArgument)
.map(jsonArgument -> GSON.toJson(jsonArgument, ArrayList.class))
.map(gson -> GSON.fromJson(gson, MyObject[].class))
.map(myObjectArray -> Arrays.asList(myObjectArray));
Benifits:
we are not using reflection here. :)

Categories

Resources