So my question is kind of a spin-off of this answer. I have a JSON response of
{
"Key1": {...},
"Key2": {...}
}
and I would like to map it into an object. Since I can't make a wrapper object for what could be 100+ keys, I'd put it all in a Map.
This answer would be great, but I'm not using GSON and am having a hard time doing the same thing with Spring's RestTemplate. When I'd like to parse it to a map with an object as such:
Map<String, RequestObject> map = restTemplate.getForObject("https://example.com/request.json", Map.class);
My RequestObject becomes a LinkedHashMap instead. So map becomes a Map<String, LinkedHashMap>. Which in turn also seems to be holding more LinkedHashMaps. Will I be needing something more complicated like writing my own Jackson Deserializer?
edit:
Unlike in this question (possible duplicate), I do not wish to obtain a generic wrapper. The object will always be the same, but the key varies every time. If it were something as the following:
{
"Sample":{
"Key":"2",
"Object":{
"Id":"0"
}
}
}
I could map it to:
class Sample{
String key;
CustomObject object;
}
class CustomObject{
String id;
}
But since it's of the following form:
{
"Key1":{
"Id":"0",
"Value":"X"
},
"Key2":{
"Id":"1",
"Value":"Y"
},
"Key3":{
"Id":"2",
"Value":"Z"
}
}
I'm not so sure how to map it into a useful representation of the objects represented by each key. (Id & Value here). I can't imagine needing to create a class for every key, so transforming it to a map seems a decent idea. This is not what this question describes.
Related
I'm using Jackson and MongoDB in Java. I want to serialize part of an object as "normal JSON" with Jackson, while a specific property should be serialized as "extended JSON". The reason being to keep the data types of that particular part of the structure intact (i.e. not lose info on e.g. Double vs Int64 vs Int32).
For example, if I have a class:
public class ExampleClassToBeSerialized {
#JsonProperty("itemList")
public List<MyObjectIntendedAsExtendedJson> itemList;
#JsonProperty("something")
public boolean something;
#JsonProperty("somethingElse")
public long somethingElse;
}
public class MyObjectIntendedAsExtendedJson {
public long thisShouldBeExtendedJson;
}
Here I'd like the outer object with something and somethingElse to be plain JSON, while the serialization of itemList should be done as extended JSON, again, to keep datatypes since it might again be used in MongoDB. I'd expect a result similar to this:
{
"itemList": [{
"thisShouldBeExtendedJson": { "$numberLong": "66666666666" }
},{
"thisShouldBeExtendedJson": { "$numberLong": "77777777777" }
}],
"something": false,
"somethingElse": 123123123123
}
I'm unsure how to achieve this particular result. I've managed to get e.g. the itemList as strings which contain extended JSON by using a StdSerializer<MyObjectIntendedAsExtendedJson> and creating e.g. a Document d = new org.bson.Document() and calling d.toJson(JsonWriterSettings.builder().outputMode(JsonMode.EXTENDED).build()). As mentioned, this ends up being an extended JSON object inside a string. I'd like it to be part of the overall string representing the total JSON. In my example only the list would be used for MongoDB interaction, and therefor only that part needs to be extended JSON.
Is there any way to achieve my particular case of part plain JSON, part extended JSON?
I try to read Json file with Jackson and depends on it, make another Json output. The problem is to read Json file, I created a POJO object with fields, that represent in Json. But it could change and there are could be appear another values, that I didn't represent in POJO. So my logic there, is will add fields, depends on read values I've been get from Json. Is there are any way to do this, or I came not right way..
public String makeOutput() {
Collection<String> key = map.get("POJO");
for (String name : key) {
requestOut = mock.reflect(CAPM.class)
.field("name", "Anna")
.field("age", 12)
// there is field 'name', that didn't represent in POJO
.field(name, "Green")
.map(gson::toJson)
.val();
}
return requestOut;
}
I'm using mockNeat lib. for generate Json. "map" is a MultiValuedMap<String, String>
I have a web project with 2 Java Entities(Lets Say E1,E2) like how mybatis and VO works.
Object structure:
class E1{
String a;
.... n other data members
E2 e2;
}
class E2{
String b;
.... n other data members
}
Is it possible to make a single class in Android project, i.e.
class E1 {
String a;
String b; //This Data member belongs to class E2
}
and parse it with the help of a framework (like Jackson) or I have to write a custom class for that?
My JSON Data will look like this:
{
"E1": {
"a": "some data",
.
.
.
"E2": {
"b": "some data",
.
.
other data
}
}
}
Is there any API which can do this?
I asked this because with my web Application its not just 2 Class but atleast 10 interconnected class and I am not Using them in my android app. So don't wanna replicate the same classes in android app.
Also if you can suggest any other possible way.
It would be a very bad design practice/approach, making things very difficult to debug, error prone and not future proof (think about it, what if you add to one of the 10 classes a field that conflict with another class' field?).
Anyway, if you still want to trick your way out of the correct approach that would be to have 10 classes, I am not aware of any lib that provides you with this feature. You could parse json ==> 10 Java Map, then merge the 10 Map through the Map::putAll method and finally pass the obtained Map that contains all the objects to Jackson.
Your best bet is to use #JsonAnySetter annotation from Jackson library on the receiver POJO.
public class E1{
public String a;
private Map<String, Object> paramMap = new HashMap<>();
#JsonAnyGetter
public Map<String, Object> getParamMap() {
return paramMap;
}
#JsonAnySetter
public void setParamMap(String s, Object o) {
paramMap.put(s, o);
}
}
This will put every unimplemented attributes in a HashMap.
In combination with #JsonAnyGetter, the serialization of the receiver POJO will give the same result as the JSON input.
I have a bunch of Java objects that are being serialized with Jackson. All of the serialized types look something like this:
class MySampleClass {
#JsonProperty("propName1")
private MyCustomType propName1;
#JsonProperty("propName2")
private MyOtherCustomType propName2;
#JsonCreator
public MySampleClass(#JsonProperty("propName1") MyCustomType propName1, #JsonProperty("propName2") MyOtherCustomType propName2) {
this.propName1 = propName1;
this.propName2 = propName2;
}
}
Is there any case where converting instances of this class to a Map<String, Object> and then converting the map to JSON will not be desearializable back into the original Java object?
That'll do it, unless you are receiving an array of these objects. If that's the case, then you can use MySampleClass[].
JSON is defined in RFC 7159. From here:
An object is an unordered collection of zero or more name/value
pairs, where a name is a string and a value is a string, number,
boolean, null, object, or array.
(emphasis mine)
So, a JSON object must have Strings as keys, and values can be one of a handful of Object types.
An API my application is communicating with sends responses that look like:
{
Code: 200,
Message: "HELLO",
Data: []
}
The Data field is always an array of SOMETHING. But that something could be a single node of text, another array of something else, or any other of an assortment of different objects.
In the below example, the data node is an array of an array of car objects.
Data: [ [ {car:1}, {car:2} ] ]
Another return type could be an array of insect objects:
Data: [ {insect : spider} ]
I would like to design a Gson object to handle this and was wondering what the best way would be.
My first thought is to have an abstract class that holds the Code and Message fields, and then have many sub-types that all have their own Data field. Then I would just call .fromJson() passing it the sub-class.
Is there a more optimal way to design it so that Gson would handle the differences?
I figured out what I believe is the best answer. Fairly straightforward!
Make the class generic and supply the type by creating a TypeToken before passing to Gson:
public class Response<T> {
private String code;
private String message;
private List<T> data;
}
Then when using Gson:
Type myCarListResponse = new TypeToken<Response<List<Car>>>(){}.getType();
Response<List<Car>> response = gson.fromJson(json, myCarListResponse);
Replace > with the type you are expecting from the Data node. The above example satisfies the first example from the original post.
To satisfy the second example:
Type myInsectResponse = new TypeToken<Response<Insect>>(){}.getType();
Response<Insect> response = gson.fromJson(json, myInsectResponse);
In Jackson, you can use #JsonAnyGetter/Setter to achieve this.
Refer http://www.cowtowncoder.com/blog/archives/2011/07/entry_458.html, http://wiki.fasterxml.com/JacksonFeatureAnyGetter