Gson to json string conversion - java

Hello all I am setting value to an object and then running gson.tojson(myObject)
This works fine and the output looks like:
{"val1":22,"val2":4,"val3":34,"val4":1046.0,"val5":"hello","val6":true}
However I now need my json string to look like
{"myJson": {"val1":22,"val2":4,"val3":34,"val4":1046.0,"val5":"hello","val6":true}}
is there a built in way to do this or should I just do sting concat?

Yes, you just need to get the JsonTree and add an inner object to it
JsonElement innerObject = gson.toJsonTree(myObject);
JsonObject outerObject = new JsonObject();
outerObject.add("myJson",innerObject);
Now, outerObject has innerObject so you can take it from there, convert it to String if you want.
String json = outerObject.toString();

I don't know if there is a option for that with Gson but you can create a wrapper class for your object :
class ObjectWrapper {
Object myJsonObject;
}
And use gson.toJson() on the wrapped object.

You can create a wrapper class which has your object set in its property "myJson".
public class Wrapper {
<Yourclass> myJson;
public Wrapper(<Yourclass> obj){
myJson = obj;
}
}
Afterwards create the JSON based on the Wrapper.

Related

How to convert List<?> to List<Object> in java?

How to convert List<?> to List in java?
For example I have this class
#Data
public class Example {
private List<?> data;
}
and I used in this function
#PostMapping("/getResult")
#ResponseBody
public Result getResult(#RequestBody String json) {
Gson gson = new Gson();
Example xmpl = gson.fromJson(json, Example.class);
List<MyObject> source = (List<MyObject>)xmpl.getData(); //==> error
// get Result
return result;
}
It will give this error
class com.google.gson.internal.LinkedTreeMap cannot be cast to class com.myproject.MyObject
EDITED:
The real problem is not from converting ? to object, but from converting LinkedTreeMap to the object
WORKAROUND :
String jsonData = gson.toJson(xmpl.getData());
MyObjectBean[] objs = gson.fromJson(jsonData,MyObjectBean[].class);
You could go with two solutions, to start with:
You can change the Generic type, this way You don't say data is any collection, but it's a collection of type <T>. Now You can create classes with given type anywhere You need it.
Generic value <?> means in general that you don't care what is inside, and probably You won't read it anyway. When You are interested only if collection is null or what it's size.
When You need to do something with it, then use Generic types.
Example:
public class Example<T> {
private List<T> data;
}
Now inside of your controller, create a private class, to deserialize your payload.
static class MyObjectExample extends Example<MyObject>{
}
Now you can use it do decode JSON:
MyObjectExample xmpl = gson.fromJson(json, MyObjectExample.class);
List<MyObject> source = xmpl.getData();
Now if your code can be serialized to MyObject it will work.
Spring supports deserialization also.
If you have a #RestController annotation added to your Controller class
Example:
#PostMapping("/getResult")
public Result getResult(#RequestBody MyObjectExample xmpl) {
// get Result
return result;
}
Or you can add
consumes = MediaType.APPLICATION_JSON_VALUE
to your REST method.
Try using Spring to convert your value for you.
You can find more
GetMapping and PostMapping
tutotrial
The real issue is not when converting ? to MyObject, but the LinkedTreeMap to MyObject, from
this explanation
by #harsh
so I did this workaround
String jsonData = gson.toJson(xmpl.getData());
MyObjectBean[] objs = gson.fromJson(jsonData,MyObjectBean[].class);

Match JSON String to new POJO Object

I am using Spring RestTemplate to communicate with an provided REST service that delivers JSON. To Map the response I am using Jaxon, but I will gladly switch to anything else that works.
I would like to create an POJO that contains sub-content of the delivered data but in a different Structure.
It boils down to this:
Source: { "a": "val_a", "b" : {"c" : "val_c", "d": "val_d"}}
#JsonIgnoreProperties(ignoreUnknown = true)
class Foo {
// should contains the content of `"a": "val_a"`
// but contains null
private Baa;
// getter and setter
}
#JsonIgnoreProperties(ignoreUnknown = true)
class Baa {
private String a;
// getter and setter
}
// This should be the operation that is done internally by Spring when calling
// ResponseEntity<Foo>response = restTemplate.exchange(url, HttpMethod.GET, entity, Foo.class);
// response.getBody();
private Foo read(String s) {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
return mapper.readValue(s, Foo.class);
}
The result of the deserialization is an empty Baa object. The actual JSON and POJO Object structure is more complex but this sums it up.
Any Technology that achieves this would be welcome.
The only possibility I came up with is deserializing the JSON in the provided structure and write a Converter class that generates the desired Object but I was hoping to avoid this.
----- Update/clarification ------
The problem is, that the property a should be mapped within class Baa, which lies within Foo but is provided in the root path (is this the right term?) of the provided JSON objekt
public class Foo {
private String a;
private B b;
// getters setters
}
public class B {
private String c;
private String d;
// getters setters
}
Should map with no additional annotations with your code. If you're having a particular code with a non trivial example then post your actual code in whole.
Update on your clarification: no you can't do that with annotations as I said in my comment. You will have to write the custom deserialiser. Check out this answer: Jackson: is it possible to include property of parent object into nested object?
If you don't want to write the java bean that rappresent the JSON structure, you have to use a different library. Jackson forces you to create a java structure that reflects the JSON structure. In my opinion Jackson works great and i suggest you to use it, but the alternative could be JSON library.
With this one you can select only the element you want from the json, and map it to the bean you want.
Little example:
JSONObject response = new JSONObject("{\"a\": \"val_a\", \"b\" : {\"c\" : \"val_c\", \"d\": \"val_d\"}}");
JSONObject bObject = response.getJSONObject("b");
String cElement = (String) elenco.get("c");
The value of bObject is {"d":"val_d","c":"val_c"}, and the value of cElement is val_c
This libray uses JSONObject and JSONArray generic objects, to map the content of the json to a java object.

Complex Json Object to Java object with Map field with Gson

I have a Json structure like so:
{
"Pojo" : {
"properties" : {
"key0" : "value0",
"key1" : "value1"
}
}
}
I want my final result to look something like this:
public class Pojo {
public Map<String, String> properties;
}
but instead I get something like this:
public class Pojo {
public Properties properties;
}
public class Properties {
public String key0;
public String key1;
}
Right now all I am doing for parsing the Json is this:
new Gson().fromJson(result, Pojo.class)
Thoughts on what I would need to do to get this set up correctly? I do not have the ability to change the Json return object's structure.
Gson is trying to match the JSON field name to a POJO field, so you above JSON is implying the top level object has a field named 'Pojo'. In fact, it is indicating the following class structure,
class Container {
MyObject Pojo;
}
class MyObject {
Map<String, String> properties;
}
where the name of the classes MyObject and Container are completely arbitrary. Gson matches field names, not object type names.
You can deserialize that object with a simple statement -
Container container = gson.fromJson(result, Container.class);
Your map with then be container.Pojo.properties
If you would rather not have the extra container class, you can parse to a Json tree first, and then extra the part that you an interested in --
JsonElement json = new JsonParser().parse(result);
// Note "Pojo" below is the name of the field in the JSON, the name
// of the class is not important
JsonElement pojoElement = json.getAsJsonObject().get("Pojo");
Pojo pojo = gson.fromJson(pojoElement, Pojo.class);
Then your map is in pojo.properties, which is what I think you want. I have left off error checking for clarity, but you will probably want to add some.
Try this:
JSONObject obj1=new JSONObject(jsonString);
JSONObject obj2=obj1.getJSONObject("Pojo");
JSONObject obj3=obj2.getJSONObject("properties");
String key1=obj3.getString("key0");
String key2=obj3.getString("key1");
For more reference try the link:
https://androidbeasts.wordpress.com/2015/08/04/json-parsing-tutorial/

Gson-> Json to deserialize List of custom objects

I am trying to serialize and de-serialize an ArrayList of Java POJOs using Gson on Json objects
I have an object MyClass as
public class MyClass{
private int type
private int pos;
private Object value;
}
I have an ArrayList of these objects, which I serialize as
List<MyClass> values= null;
String json = new Gson().toJson(retValues);
The json string is
[{"type":4,"pos":1,"value":15}]
I try to deserialize it as
Type myType = new TypeToken<ArrayList<MyClass>>() {}.getType();
List<MyClass> test=new Gson().fromJson(json, myType);
I get an error
The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter#1141ddf failed to deserialized json object [{"type":4,"pos":1,"value":18}] given the type java.util.ArrayList<abc.MyClass>
Any input much appreciated!
I figured it out. I added 2 things, I don't know which one made it work.
- I added a no-arguments constructor to MyClass
- I made MyClass implement serializable.
And it works!
Thanks for your help.

GSON: Typing JSON data to Java class where class name is stored in string

I'm using Google's GSON Library to convert JSON data to Java objects. The issue is that class name of the Java objet is being passed in the JSON data as well, so it is available only as a string. I'm not too familiar with Java so I don't understand how to declare an object when the class name is stored as a string.
Also, the same is the case for the method that I will be calling after the data is initialized.
Here's the relevant code so far:
request = gson.fromJson( rawData.toString(), JSONRequest.class );
String method = request.getMethod();
String data = request.getData();
String dataClass = request.getDataClass();
// convert data into an object of dataClass and execute method by passing dataObject
dataClass dataObject = gson.fromJson( data, dataClass.class );
result = method( dataObject );
This seems like a very crude way to accomplish the data to object conversion. Is there a better way? If not, how can I fix the code?
With the example code in the original question, dataClass.class will always be String.class, which I doubt is the correct target type to deserialize to.
I think the following is what was intended to be demonstrated. (I'm not sure what implementation of JSONRequest was used in the original question. I'll just make one up.)
If the target type is really not known, and it's not a sub-type of some known parent type, then reflection would be necessary to invoke the method. (This assumes that the target method does not require any parameters.)
import java.io.FileReader;
import java.lang.reflect.Method;
import com.google.gson.Gson;
public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
// input JSON:
// {
// "dataClass":"com.stackoverflow.q6647866.MyObject",
// "method":"myMethod",
// "data":"{\"name\":\"fubar\"}"
// }
JSONRequest request = gson.fromJson(new FileReader("input.json"), JSONRequest.class);
Class targetClass = Class.forName(request.dataClass);
System.out.println("targetClass: " + targetClass);
Object dataObject = gson.fromJson(request.data, targetClass);
Method method = targetClass.getMethod(request.method);
method.invoke(dataObject);
}
}
class JSONRequest
{
String method;
String data;
String dataClass;
}
class MyObject
{
String name;
public void myMethod()
{
System.out.println("running my method...");
}
}
This seems like a very crude way to accomplish the data to object conversion. Is there a better way?
That's about as good as it gets, if the target data type and method to invoke are both completely unknown and only provided in the incoming JSON.

Categories