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/
Related
I would like to know after the deserialization with Jackson what fields where set by the Json input (even null), so I can than distinguish the null fields than where set on null from the one that where not specified in Json.
This question comes after my previous one about BeanDeserializerModifier.
public class Dto {
public Collection<String> deserializedFields;
// or even better a collection of reflection fields of the object.
}
public MyFooDto extends Dto {
public Integer myField1;
#PossiblySomeJacksonAnnotation (include, exclude, map on other name, special deserializer, etc...)
public SomeDatatype myField2;
}
Example: by deserializing {"myField1": null} I would like to have deserializedFields = ["myField1"], and by deserializing {} I would like to have deserializedFields = [].
I already tried within a custom deserializer and a BeanDeserializerModifier, but still I cant intercept the list of fields inside the Json object (or if I do so it already consumates the JsonParser and it can't be deserialized then).
In the best case I would also get the reflection list of the MyFooDto Fields that have been set...
Do you see how I could proceed?
Thank you Community!
The most straightforward way is to add code in each setter to add the currently set variable name to a List. E.g. :
public class Dto {
public List<String> deserializedFields = new ArrayList<>();
}
and inside MyFooDto setters like:
public void setMyField1(Integer myField1) {
deserializedFields.add("myField1");
this.myField1 = myField1;
}
That's a lot of work if there are hundreds of such setters. An alternative for such a case is to parse JSON into a tree first, traverse it to get JSON property names to add in a collection and then convert the tree to MyFooDto. E.g. (assuming you have a ObjectMapper mapper and json below is a String with your example JSON):
ObjectNode tree = (ObjectNode) mapper.readTree(json);
ArrayNode deserializedFields = mapper.createArrayNode();
tree.fields().forEachRemaining(e -> deserializedFields.add(e.getKey()));
tree.put("deserializedFields", deserializedFields);
MyFooDto dto = mapper.treeToValue(tree, MyFooDto.class);
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.
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.
I want to deserialize json objects to specific types of objects (using Gson library) based on type field value, eg.:
[
{
"type": "type1",
"id": "131481204101",
"url": "http://something.com",
"name": "BLAH BLAH",
"icon": "SOME_STRING",
"price": "FREE",
"backgroundUrl": "SOME_STRING"
},
{
....
}
]
So type field will have different (but known) values. Based on that value I need to deserialize that json object to appropriate model object, eg.: Type1Model, Type2Model etc.
I know I can easily do that before deserialization by converting it to JSONArray, iterate through it and resolve which type it should be deserialized to. But I think it's ugly approach and I'm looking for better way. Any suggestions?
You may implement a JsonDeserializer and use it while parsing your Json value to a Java instance. I'll try to show it with a code which is going to give you the idea:
1) Define your custom JsonDeserializer class which creates different instance of classes by incoming json value's id property:
class MyTypeModelDeserializer implements JsonDeserializer<MyBaseTypeModel> {
#Override
public MyBaseTypeModel deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
JsonElement jsonType = jsonObject.get("type");
String type = jsonType.getAsString();
MyBaseTypeModel typeModel = null;
if("type1".equals(type)) {
typeModel = new Type1Model();
} else if("type2".equals(type)) {
typeModel = new Type2Model();
}
// TODO : set properties of type model
return typeModel;
}
}
2) Define a base class for your different instance of java objects:
class MyBaseTypeModel {
private String type;
// TODO : add other shared fields here
}
3) Define your different instance of java objects' classes which extend your base class:
class Type1Model extends MyBaseTypeModel {
// TODO: add specific fields for this class
}
class Type2Model extends MyBaseTypeModel {
// TODO: add specific fields for this class
}
4) Use these classes while parsing your json value to a bean:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MyBaseTypeModel.class, new MyTypeModelDeserializer());
Gson gson = gsonBuilder.create();
MyBaseTypeModel myTypeModel = gson.fromJson(myJsonString, MyBaseTypeModel.class);
I can not test it right now but I hope you get the idea. Also this link would be very helpful.
#stephane-k 's answer works, but it is a bit confusing and could be improved upon (see comments to his answer)
Copy https://github.com/google/gson/blob/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java into your project. (It's ok; these classes are designed to be copy/pasted https://github.com/google/gson/issues/845#issuecomment-217231315)
Setup model inheritance:
// abstract is optional
abstract class BaseClass {
}
class Type1Model extends BaseClass {
}
class Type2Model extends BaseClass {
}
Setup GSON or update existing GSON:
RuntimeTypeAdapterFactory<BaseClass> typeAdapterFactory = RuntimeTypeAdapterFactory
.of(BaseClass.class, "type")
.registerSubtype(Type1Model.class, "type1")
.registerSubtype(Type2Model.class, "type2");
Gson gson = new GsonBuilder().registerTypeAdapterFactory(typeAdapterFactory)
.create();
Deserialize your JSON into base class:
String jsonString = ...
BaseClass baseInstance = gson.fromJson(jsonString, BaseClass.class);
baseInstance will be instanceof either Type1Model or Type2Model.
From here you can either code to an interface or check instanceof and cast.
use https://github.com/google/gson/blob/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java
then configure it with
public static final class JsonAdapterFactory extends
RuntimeTypeAdapterFactory<MediumSummaryInfo> {
public JsonAdapterFactory() {
super(MyBaseType.class, "type");
registerSubtype(MySubtype1.class, "type1");
registerSubtype(MySubtype2.class, "type2");
}
}
and add the annotation:
#JsonAdapter(MyBaseType.JsonAdapterFactory.class)
to MyBaseType
Much better.
If you have a lot of sub types and you do not want to or cannot maintain a list of them, you can also use an annotation based approach.
Here is the required code and also some usage examples:
https://gist.github.com/LostMekka/d90ade1fe051732d6b4ac60deea4f9c2
(it is Kotlin, but can easily be ported to Java)
For me, this approach is especially appealing, since I write a small library that does not know all possible sub types at compile time.
my server return json and am using Jackson for deserailise the response
in the response i have key called Car the value of the car may be an array or an object then how can define my class
Response
if more than object exist then array of object will return otherwise an object will return
{
"Car":"[{obj,obj,obj}]"
}
{
"Car":"obj"
}
the json format you posted has no array only strings. the first is car the second is [{obj,obj,obj}]
The json should look like this: {"Car":["","",""]} and can be mapped to this java class:
public static class JsonTest extends Hashtable<String, List<String>> {
public JsonTest(){};
}
your second json string is of a different format it should have the array notation too:
{ "Car":[ "" ] }