converting java DTO list into JSON object - java

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...

Related

Gson ignore too many properties in nested object

I have a JSON with this structure:
{
"firstProperty": true,
"thisIsAString": "hi",
"myList": [
{"myBool": true},
{"myBool": false, "otherfield": true}
]
}
The myList is a List<MyClass> in the target class.
This MyClass only has the myBool field which causes the first element of the array to properly deserialize but unfortunately deserializing the second element causes it to fail with the error message Unknown property 'myBool' for class my.package.MyClass at JSON path $.otherfield.
Is there any way to just ignore fields in the JSON that don't exist in the target class of the deserialization? Maybe it is because of nested objects?
I already tried to add a custom type adapter like seen here but it didn't even call the method (the target class is a record which is why i have to use the third party library com.github.Marcono1234:gson-record-type-adapter-factory to deserialize it)
AFAIK, Gson will ignore unknown fields automatically while deserialization. So, I assume that you have already created these 2 classes which look like:
public class MyClass {
private Boolean myBool;
// getter, setter and toString
}
public class MyResult {
private Boolean firstProperty;
private String thisIsAString;
List<MyClass> myList;
// getter, setter and toString
}
Then you can serialize your JSON string as follows:
String yourJsonStr = "" +
"{\n" +
" \"firstProperty\": true,\n" +
" \"thisIsAString\": \"hi\",\n" +
" \"myList\": [\n" +
" {\"myBool\": true},\n" +
" {\"myBool\": false, \"otherfield\": true}\n" +
" ]\n" +
"}";
Gson gson = new Gson();
MyResult myResult = gson.fromJson(yourJsonStr, MyResult.class);
System.out.println(myResult.toString());
Console output:
MyResult{firstProperty=true, thisIsAString='hi', myList=[MyClass{myBool=true}, MyClass{myBool=false}]}
I found the issue, the third party library I use to deserialize into records has a TypeAdapterFactory which has a option to ignore unknown properties which is set to false per default.
Turning this option on produces the expected output.

In Java how to easily get the value of a nested key from a JSON String / Object

I am using Java.
I have a string that I have converted to a JSON Object.
I want to extract the value of one of the Keys.
At the moment I am using this code:
String imageId = myJsonObject.getJSONObject("meta")
.getJSONObject("verification")
.getJSONObject("derivedData")
.getJSONArray("images")
.getJSONObject(0)
.getString("imageID");
This code works but surely there must be an easier way. In javascript I could access the value simply by writing this:
myJsonObject.meta.verification.derivedData.images[0].imageId
You may need to install library such as JsonPath to help you select values from a JSON object
An example to help understand better.
You can use external library Gson
Gson gson=new Gson();
/*You can convert to your DTO as well */
Map<Object,Object> map = gson.from(myJsonObject,Map.class);
Other way is using objectmapper example of fasterxml.
ObjectMapper objectMapper=new ObjectMapper();
/*You can convert to your DTO as well */
objectMapper.readValue(data, Map.class);
Try JsonNode by below step
String imageId= jsonNode.
findPath("meta")
.findPath("verification")
.findPath("derivedData")
.findPath("images")
.get (0).findPath ("imageID").asText ();
You need to use the 'Java API for JSON Binding' JSON-B instead of JSON-P. Using JSON-B you can serialize and deserialize between Java objects and data streams and access values of objects POJO style (similar to what you expect).
API details can be found here
A quick start tutorial can be found here and at many website only google search away..
I have created a small class for this purpose which can basically get value from json using a path only used google.gson
https://github.com/izeryab/JsonParser
Here is how to use this for getting nested value from json:
public class Main {
public static void main(String[] args) {
String json = "{\"data\":[{\"stuff\":[\n" + " { \"onetype\":[\n"
+ " {\"id\":1,\"name\":\"John Doe\"},\n" + " {\"id\":2,\"name\":\"Don Joeh\"}\n"
+ " ]},\n" + " {\"othertype\":[\n" + " {\"id\":2,\"company\":\"ACME\"}\n" + " ]}]\n"
+ "},{\"otherstuff\":[\n" + " {\"thing\":\n" + " [[1,42],[2,2]]\n" + " }]\n" + "}]}";
String name = JsonUtil.getJsonElementFromJsonStringUsingPath("data>0>stuff>0>onetype>0>name", json, ">").getAsString();
int id= JsonUtil.getJsonElementFromJsonStringUsingPath("data>0>stuff>0>onetype>0>id",json,">").getAsInt();
System.out.println("id : "+id);
System.out.println("name : "+name);
}
}
Corresponding JAVA DOCS:
https://izeryab.github.io/JsonParser/JsonUtil.html
You can use GSon, I've used it before (see below)
// Convert to a JSON object to print data
JsonParser jp = new JsonParser(); //from gson
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object.
JsonArray jsonDataArray = rootobj.getAsJsonArray("data");
JsonPrimitive totalJson = rootobj.getAsJsonPrimitive("total");
JsonPrimitive nextJson = rootobj.getAsJsonPrimitive("next");

How to create a new json string by changing one particular field in it?

I need to blur the user id present in my original json string with another user id. After that I will construct a new json string with everything same but the only difference will be the user id is different.
As an example, if my original json string is like this -
{
"user_id":{"long":1234},
"client_id":{"int":0},
"affinity":[
{
"try":{"long":55793},
"scoring":{"float":0.19}
},
{
"try":{"long":1763},
"scoring":{"float":0.0114}
}
]
}
Then my new json string will be - The only difference is I have a new user id in it and apart from that everything is same.
{
"user_id":{"long":98765},
"client_id":{"int":0},
"affinity": [
{
"try":{"long":55793},
"scoring":{"float":0.19}
},
{
"try":{"long":1763},
"scoring":{"float":0.0114}
}
]
}
The only problem I have is, I won't have json string in the above format only so I cannot use POJO to serialize my json string since my json string will have different formats but user_id field will always be like that in all my json string and it will be long as well. The other fields might be different depending on the json string I have.
I am using Gson to do this. I have got the below method but not sure how can I construct a new json with newUserId in it and everything should be same?
private static String creatNewJson(String originalJsonResponse, long newUserId) {
JsonElement jelement = new JsonParser().parse(originalJsonResponse);
JsonObject jobject = jelement.getAsJsonObject();
jobject = jobject.getAsJsonObject("user_id");
// not sure what I should do here to construct a new json with newUserId
}
Or Gson is not the right way to do this? Should I be usingg regular expressions for this?
How about input.replaceAll("(\"user_id\":\\{\"long\":)\\d+", "$1" + newID)?

Java Objects to JSON, parse using javascript

I am trying to send an array of pojo's as a response to an ajax call.
Inside of my pojo, I have the following toString():
#Override
public String toString() {
return "Expense [period=" + period + ", description=" + description +
", category="+ category + ", subCategory="+subCategory+", "
+ "amount="+amount+", store="+store+"]";
}
Then, inside of my doGet method, I build up the arraylist of pojos, and am trying to write them out, using:
Gson gson = new Gson();
String json = gson.toJson(expensesForPeriod);
out.write(json);
Where expensesForPeriod is an arraylist of expense objects.
Is this the correct way to send an arraylist of json objects?
On the javascript side, how would I convert the json string to an array of objects, and iterate over them?
You should use #Expose before each of your instance members in the class definition, then call the Gson file on that instance.
For java side:
you shouldn't override toString method, just need to use Gson to parse object to json string
For javascript side:
you can follow this tutorial: link

Reverse ToStringBuilder : convert string to object

Is there a way to convert my output from ToStringBuilder back to java object?
I am looking for an easy way to represent a Java object in readable text file and being able to convert back and forth between string and object.
Thanks,
You must define a strict format and follow it with a parser. There are two accepted formats:
XML - you can use java.beans.XMLEncoder
JSON - use Jackson or gson
If you don't choose these formats you will have to handle the parsing yourself.
The ToStringBuilder does not seem to have a reverse equivalent. Furthermore it is wrong to use this string representation for such purposes - it is meant only for debug.
You'll have to parse your string representation of the object and then construct a new object initialised with those values.
If you want to keep it generic and have it work for any object type, you can use Apache BeanUtils to help.
For example, if your string representation is:
Person#7f54[name=Stephen,age=29,smoker=false]
Parse out the class name, fields and values. Then use BeanUtils to construct a new Person:
String className = "Person";
Class beanClass = Class.forName(className);
Person myPerson = (Person)beanClass.newInstance();
BeanUtils.setProperty(myPerson, "name", "Stephen");
BeanUtils.setProperty(myPerson, "age", "29");
BeanUtils.setProperty(myPerson, "smoker", "false");
This assumes that your Person class is a bean and exposes getters/setters for its fields.
Sean, I came across your question while looking for a simple test case converter based on a reflection-based String output of an object. While a more robust library for json or XML is certainly important for a wide range of input, this is handy for quick and dirty test cases. It handles simple, non-nested POJOs. Its only dependency is apache commons.
I'm using this toString format:
#Override
public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
Here is the class:
public class FromStringBuilder {
/**
* Parses a string formatted with toStringBuilder
*
* #param input - ex. "Path[id=1039916,displayName=School Home,description=<null>,...]"
* #return hashmap of name value pairs - ex. id=1039916,...
*/
public static Map<String, String> stringToMap(String input) {
LinkedHashMap<String, String> ret = new LinkedHashMap<String, String>();
String partsString = StringUtils.substringBetween(input, "[", "]");
String[] parts = partsString.split(",");
for (String part:parts) {
String[] nv = part.split("=");
if (!StringUtils.equals("<null>", nv[1])) {
ret.put(nv[0], nv[1]);
}
}
return ret;
}
public static <T> T stringToObject(String input, Class<T> clazz) throws IllegalAccessException, InvocationTargetException, InstantiationException {
Map<String, String> map = stringToMap(input);
T ret = clazz.newInstance();
BeanUtils.copyProperties(ret, map);
return ret;
}
}
XStream library is the perfect one
Here is an example of using Gson:
public class GsonTest {
static class Name { String first; String last; }
static class Data { int number; Name name = new Name(); }
public static void main(String[] args) {
Gson gson = new Gson();
Data data1 = new Data();
data1.number = 1;
data1.name.first = "Joe";
data1.name.last = "Smith";
print("data1", data1);
String jsonString = gson.toJson(data1);
System.out.println("jsonString: " + jsonString);
Data data2 = gson.fromJson(jsonString, Data.class);
print("data2", data2);
}
private static void print(String id, Data data) {
System.out.println(id + " :"
+ " number=" + data.number
+ " name.first=" + data.name.first
+ " name.last=" + data.name.last);
}
}
Output
data1 : number=1 name.first=Joe name.last=Smith
jsonString: {"number":1,"name":{"first":"Joe","last":"Smith"}}
data2 : number=1 name.first=Joe name.last=Smith
Speed
Gson should be roughly as fast as any other comparable reflection-based Object<->Text serialization framework, but I do not have benchmark data.
Bean Support
Unlike XStream(optionally) and java.beans.XMLEncoder/XMLEncoder, Gson does not use a class's setter and getter methods. Rather it reads and writes the member fields of the class directly, similar to Java binary serialization (ObjectOutputStream, etc.) While Gson should be able to properly marshal and unmarshal most JavaBeans, this implementation detail of Gson must be kept in mind and accounted for.
Pretty-printed JSON Output
By default GSON outputs JSON all on one line, as an optimization. It can output JSON that is slightly easier to read. Do this by constructing the Gson object in a slightly different way:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
The JSON output (continuing the example above), now looks like:
{
"number": 1,
"name": {
"first": "Joe",
"last": "Smith"
}
}
instead of
{"number":1,"name":{"first":"Joe","last":"Smith"}}

Categories

Resources