Attached is my json. I am receiving this from an endpoint. I have the object type in my consuming app. the object contains; success, message and loggedInMember (which is an object). In the json, the feeClasses contains a lot of fields and objects etc which is why i have not included the whole json. I am only interested in the success and message fields.
{
"header":{
"messageId":null,
"receivedTimestamp":1611246394839,
"replyTo":null,
"redelivered":false,
"originator":null
},
"internalId":null,
"auditPoints":[
],
"success":true,
"message":"",
"loggedInMember":{
"feeClasses":{
...CONTAINS A LOT OF FIELDS...
}
}
}
I am trying to map this response to the object type, hence essentially leaving loggedInMembers null. This is my test I am trying to run:
public void test() throws JsonProcessingException
{
//String json = "{\"header\":{\"messageId\":null,\"bucketNumber\":null,\"senderSubId\":null,\"senderLocationId\":null,\"onBehalfOfCompId\":null,\"onBehalfOfSubId\":null,\"onBehalfOfLocationId\":null,\"correlationId\":null,\"receivedTimestamp\":1611246394839,\"replyTo\":null,\"redelivered\":false,\"originator\":null},\"internalId\":null,\"auditPoints\":[],\"success\":true,\"message\":\"\",\"loggedInMember\":{\"memberLoginName\":\"BMARTINTEST\",\"memberId\":\"201901241246290000036402D\",\"settlementAccountIds\":[\"201901241246290000036491D\"],\"parentMemberId\":\"1\",\"firmId\":\"990\",\"memberType\":\"INDIVIDUAL\",\"memberAccountType\":\"PROD\",\"password\":\"D1208B304FD7AA6187690A389A5040C1D9B07643\",\"feeClasses\":{\"byId\":{\"201902120947520000559606D\":{\"memberLoginName\":\"BMARTINTEST\",\"feeClassId\":\"201508041827550000942152D\",\"memberFeeClassId\":\"201902120947520000559606D\",\"allocatedDate\":{\"year\":2019,\"month\":2,\"day\":12,\"timeMillis\":1549929600000},\"firstUsedForTradeDate\":{\"year\":2019,\"month\":2,\"day\":12,\"timeMillis\":1549929600000},\"firstUsedForSettlementDate\":null,\"usableFromDate\":{\"year\":2019,\"month\":2,\"day\":12,\"timeMillis\":1549929600000},\"usableToDate\":{\"year\":2019,\"month\":2,\"day\":19,\"timeMillis\":1550534400000},\"usableToTimestamp\":1550613600000,\"usableBusinessDaysAllocated\":6,\"usableBusinessDaysRemaining\":0,\"narrative\":\"Bonus assigned to member at first-time funding of amount 4000.00 : Set expiration date/time\",\"disabled\":false,\"usableForTrade\":true,\"usableForSettlement\":true},\"202001290940390000868824D\":{\"memberLoginName\":\"BMARTINTEST\",\"feeClassId\":\"202001290940340000776406D\",\"memberFeeClassId\":\"202001290940390000868824D\",\"allocatedDate\":{\"year\":2020,\"month\":1,\"day\":29,\"timeMillis\":1580256000000},\"firstUsedForTradeDate\":null,\"firstUsedForSettlementDate\":null,\"usableFromDate\":{\"year\":2020,\"month\":1,\"day\":6,\"timeMillis\":1578268800000},\"usableToDate\":{\"year\":2020,\"month\":2,\"day\":27,\"timeMillis\":1582761600000},\"usableToTimestamp\":1582840800000,\"usableBusinessDaysAllocated\":0,\"usableBusinessDaysRemaining\":0,\"narrative\":\"Added NO_FEES_CLASS\",\"disabled\":false,\"usableForTrade\":true,\"usableForSettlement\":true},\"201901241246290000036417D\":{\"memberLoginName\":\"BMARTINTEST\",\"feeClassId\":\"201508041736360000943781D\",\"memberFeeClassId\":\"201901241246290000036417D\",\"allocatedDate\":{\"year\":2019,\"month\":1,\"day\":24,\"timeMillis\":1548288000000},\"firstUsedForTradeDate\":null,\"firstUsedForSettlementDate\":null,\"usableFromDate\":{\"year\":2019,\"month\":1,\"day\":24,\"timeMillis\":1548288000000},\"usableToDate\":null,\"usableToTimestamp\":null,\"usableBusinessDaysAllocated\":0,\"usableBusinessDaysRemaining\":0,\"narrative\":null,\"disabled\":false,\"usableForTrade\":true,\"usableForSettlement\":true}},\"empty\":false},\"legalName\":\"Martin Birch\",\"taxId\":\"345335454\",\"taxCountryId\":\"US\",\"currency\":\"USD\",\"lastTradeId\":null,\"introducingBrokerMemberId\":null,\"introducingBrokerMemberName\":null,\"introducingBrokerMemberCode\":null,\"clearedByMemberId\":\"SECOND_TEST\",\"clearedByMemberLoginName\":null,\"memberProblems\":[],\"emailNotificationEnabled\":true,\"rtafLevelId\":0,\"rtafAmount\":0,\"maxNumberOfPositionAccounts\":1,\"ciciIdentifier\":null,\"traderRequired\":false,\"interestClass\":\"INDIVIDUAL\",\"memberCreatedDate\":1548333989000,\"parentMemberLoginNames\":[\"NADEX.COM\",\"NADEX\"],\"demoStartDate\":null,\"demoEndDate\":null,\"clientIdMaxLimit\":null,\"memberAccountApplicationFieldData\":null,\"rank\":0,\"uuid\":\"201901241246290000036395D\",\"referrerId\":\"raf4qam5h00s36d\",\"testMember\":false},\"allReplyToSource\":[],\"sendToOriginatorOnly\":false}";
String json = "{\n" +
" \"header\":{\n" +
" \"messageId\":null,\n" +
" \"receivedTimestamp\":1611246394839,\n" +
" \"replyTo\":null,\n" +
" \"redelivered\":false,\n" +
" \"originator\":null\n" +
" },\n" +
" \"internalId\":null,\n" +
" \"auditPoints\":[\n" +
" \n" +
" ],\n" +
" \"success\":true,\n" +
" \"message\":\"\",\n" +
" \"loggedInMember\":{\n" +
" \"feeClasses\":{\n" +
" \n" +
" }\n" +
" }\n" +
"}";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.addMixIn(LogonResponseMessage.class, LogonResponseMixin.class);
LogonResponseMessage responseMessage = objectMapper.readValue(json, LogonResponseMessage.class);
System.out.println(responseMessage);
}
My mixin:
public abstract class LogonResponseMixin
{
LogonResponseMixin(#JsonProperty("success") boolean success, #JsonProperty("message") String message){};
#JsonIgnore
abstract Member loggedInMember();
#JsonIgnore
abstract MemberFeeClasses feeClasses();
#JsonIgnore
abstract Header header();
}
I am getting the following error: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of domain.xyz.MemberFeeClasses (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
Am i creating the mixin wrong? I have asked in a previous question and using mixin was the general consensus but it doesn't seem to play ball with me.
Thank you.
The reason why MemberFeeClasses cannot be constructed is the same as your initial problem, just add a mixin for all classes
See the example below:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import java.io.IOException;
public class Test {
//------------------------------------------------//
// PART 1 - MAIN TEST METHOD
//------------------------------------------------//
public static void main(String[] args) throws IOException {
String json = "{\n" +
" \"header\":{" +
" },\n" +
" \"success\":true,\n" +
" \"message\":\"\",\n" +
" \"loggedInMember\":{\n" +
" \"feeClasses\":{\n" +
" \"amount\": \"20\"\n" +
" }\n" +
" }\n" +
"}";
ObjectMapper objectMapper = new ObjectMapper();
//objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
objectMapper.addMixIn(LogonResponseMessage.class, LogonResponseMixin.class);
objectMapper.addMixIn(Member.class, MemberMixin.class);
objectMapper.addMixIn(MemberFee.class, MemberFeeMixin.class);
LogonResponseMessage responseMessage = objectMapper.readValue(json, LogonResponseMessage.class);
System.out.println(responseMessage.loggedInMember.feeClasses.amount);
}
//------------------------------------------------//
// PART 2 - CREATOR MIXIN
//------------------------------------------------//
static abstract class LogonResponseMixin {
LogonResponseMixin(#JsonProperty("success") boolean success,
#JsonProperty("message") String message,
#JsonProperty("header") Header header,
#JsonProperty("loggedInMember") Member member) {
}
}
static abstract class MemberMixin {
MemberMixin(#JsonProperty("feeClasses") MemberFee feeClasses) {
}
}
static abstract class MemberFeeMixin {
#JsonCreator
MemberFeeMixin(#JsonProperty("amount") String amount) {
}
}
//------------------------------------------------//
// PART 3 - EXAMPLE CLASS DEFINITION
//------------------------------------------------//
static class Header {
}
#Getter
#Setter
static class Member {
private MemberFee feeClasses;
public Member(MemberFee feeClasses) {
this.feeClasses = feeClasses;
}
}
#Getter
#Setter
static class MemberFee {
private String amount;
public MemberFee(String amount) {
this.amount = amount;
}
}
#Getter
#Setter
static class LogonResponseMessage {
private boolean success;
private String message;
private Header header;
private Member loggedInMember;
public LogonResponseMessage(boolean success, String message, Header header, Member member) {
this.success = success;
this.message = message;
this.header = header;
this.loggedInMember = member;
}
}
}
I have happily been using Google Gson to parse extract some JSON metadata of the form
{
"lowlevel": {
"average_loudness": 0.570070445538
},
"rhythm": {
"beats_count": 502,
"bpm": 128.347702026
},
"tonal": {
"chords_changes_rate": 0.0534749031067
"tuning_diatonic_strength": 0.431238204241,
"tuning_equal_tempered_deviation": 0.164615109563,
"tuning_frequency": 434.193115234,
"tuning_nontempered_energy_ratio": 0.847496032715
}
}
Using this
public class AcousticBrainzLowlevelWrapper
{
private AcousticBrainzLowLevelRhythm rhythm;
private AcousticBrainzLowLevelTonal tonal;
public AcousticBrainzLowLevelRhythm getRhythm()
{
return rhythm;
}
public void setRhythm(AcousticBrainzLowLevelRhythm rhythm)
{
this.rhythm = rhythm;
}
public AcousticBrainzLowLevelTonal getTonal()
{
return tonal;
}
public void setTonal(AcousticBrainzLowLevelTonal tonal)
{
this.tonal = tonal;
}
}
and
AcousticBrainzLowlevelWrapper low = gson.fromJson(result, AcousticBrainzLowlevelWrapper.class) ;
(Full JSON can be seen here)
but now the API has been extended to allow multiple lookups such as this url
which now returns
{
"96685213-a25c-4678-9a13-abd9ec81cf35": {
"0": {
"lowlevel": {
"average_loudness": 0.570070445538
},
"rhythm": {
"beats_count": 502,
"bpm": 128.347702026
},
"tonal": {
"chords_changes_rate": 0.0534749031067
"tuning_diatonic_strength": 0.431238204241,
"tuning_equal_tempered_deviation": 0.164615109563,
"tuning_frequency": 434.193115234,
"tuning_nontempered_energy_ratio": 0.847496032715
}
}
.....
"78787888-a25c-4678-9a13-abd9ec81cf35": {
"0": {
"lowlevel": {
......
..
The difference being that the json doesn't define what "96685213-a25c-4678-9a13-abd9ec81cf35" and "78787888-a25c-4678-9a13-abd9ec81cf35" are, or what "0" is.
So I know what they represent (MusicBrainzRecording and offset) but I cannot create a class like AcousticBrainzLowlevelWrapper to represent this, so how do I parse this new api.
Update
I tried creating
public class AcousticBrainzLowLevelList
{
private Map<String, AcousticBrainzLowlevelWrapper> data = new HashMap<>();
public Map<String, AcousticBrainzLowlevelWrapper> getData()
{
return data;
}
public void setData(Map<String, AcousticBrainzLowlevelWrapper> data)
{
this.data = data;
}
}
and then calling
AcousticBrainzLowLevelList lowMap = gson.fromJson(result, AcousticBrainzLowLevelList.class) ;
but nothing get added to the map. Unsuprisingly because data I dont' see how can i give a name since there is no consistent name at the top level.
It seems to me that your input JSON could be parsed to produce a Java class of type Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>> :
Type type = new TypeToken<Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>>>(){}.getType();
Map<String,Map<Integer,AcousticBrainzLowlevelWrapper>> result = gson.fromJson(json, type);
As I wrote it, I might as well post it:
Similar to Maurice's answer
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Map;
public class Main {
private final static String jsonSingle =
"{ \"attribute1\": \"value1\", \"attribute2\": \"value2\" }";
private final static String jsonMultiple =
"{\n" +
" \"96685213-a25c-4678-9a13-abd9ec81cf35\": {\n" +
" \"0\": { \"attribute1\": \"value1\", \"attribute2\": \"value2\" }\n" +
" },\n" +
" \"78787888-a25c-4678-9a13-abd9ec81cf35\": {\n" +
" \"0\": { \"attribute1\": \"value3\", \"attribute2\": \"value4\" }\n" +
"}}";
public static void main(String[] args) {
MyBean bean = new Gson().fromJson(jsonSingle, MyBean.class);
System.out.println(bean);
Type type = new TypeToken<Map<String, Map<String, MyBean>>>(){}.getType();
Map<String, String> myMap = new Gson().fromJson(jsonMultiple, type);
System.out.println(myMap);
}
}
MyBean class:
class MyBean {
String attribute1;
String attribute2;
public String getAttribute1() {
return attribute1;
}
public void setAttribute1(String attribute1) {
this.attribute1 = attribute1;
}
public String getAttribute2() {
return attribute2;
}
public void setAttribute2(String attribute2) {
this.attribute2 = attribute2;
}
#Override
public String toString() {
return "MyBean: <attribute1: " + attribute1 + " | " + "attribute2: " + attribute2 + ">";
}
}
Outputs:
MyBean: <attribute1: value1 | attribute2: value2>
and
{96685213-a25c-4678-9a13-abd9ec81cf35={0=MyBean: <attribute1: value1 | attribute2: value2>}, 78787888-a25c-4678-9a13-abd9ec81cf35={0=MyBean: <attribute1: value3 | attribute2: value4>}}
I have a json string that is represented as below:
"{"RequestId":255,
"RequestTime":"2016-04-08T17:00:40.327",
"Otp":"123456",
"AppName":"This is my app name",
"IsAwaitingResponse":false}"
I also have a class object below that I wish to create using the Gson library fromJson() method...
public class AccessRequest{
public int Id;
public String RequestTime;
public String Otp;
public String AppName;
public Boolean IsAwaitingResponse;
}
Now when I call the gson.fromJson method it does not error but my object is not getting set. This is the code I'm using...
Gson gson = new Gson();
AccessRequest ar;
ar = gson.fromJson(jsonString, AccessRequest.class);
It is instead setting my 'ar' variable to some strange gson object that clearly is wrong but no error is thrown.
{serializeNulls:falsefactories:[Factory[typeHierarchy=com.google.gson.JsonElement,adapter=com.google.gson.internal.bind.TypeAdapters$25#e8dad0a],
From what I can see, there is no error in my Json string ( although I am new to json ) , so I'm not really sure why this method wouldn't be working...
You probably printed the gson object instead of the ar object, as #Pillar noted in the comments.
I've tried your example and it works as expected. Also, the Id field is not being set because the name of the property does not match. You should use #SerializedName or change any of the names. This has also been noted in the comments.
This is the working example:
package net.sargue.gson;
import com.google.gson.Gson;
import org.intellij.lang.annotations.Language;
public class SO36553536 {
public static void main(String[] args) {
#Language("JSON")
String json = "{\n" +
" \"RequestId\": 255,\n" +
" \"RequestTime\": \"2016-04-08T17:00:40.327\",\n" +
" \"Otp\": \"123456\",\n" +
" \"AppName\": \"This is my app name\",\n" +
" \"IsAwaitingResponse\": false\n" +
"}";
Gson gson = new Gson();
AccessRequest ar;
ar = gson.fromJson(json, AccessRequest.class);
System.out.println("ar.getClass() = " + ar.getClass());
System.out.println("ar = " + ar);
}
public class AccessRequest {
public int Id;
public String RequestTime;
public String Otp;
public String AppName;
public Boolean IsAwaitingResponse;
#Override
public String toString() {
return "AccessRequest{" + "Id=" + Id +
", RequestTime='" + RequestTime + '\'' +
", Otp='" + Otp + '\'' +
", AppName='" + AppName + '\'' +
", IsAwaitingResponse=" + IsAwaitingResponse +
'}';
}
}
}
And this is the execution output:
ar.getClass() = class net.sargue.gson.SO36553536$AccessRequest
ar = AccessRequest{Id=0
, RequestTime='2016-04-08T17:00:40.327'
, Otp='123456'
, AppName='This is my app name'
, IsAwaitingResponse=false}
As just need to change RequestId from Id class AccessRequest.
you will get proper output.
I have a problem that I cannot resolve for a while.
Lets imagine a very simple Java class
class Foo {
public String bar;
public String baz;
}
How can I accomplish that the operation of deserialisation and consequent serialisation of some JSON request is actually immutable in terms of partial JSON objects. So that if I unserialise
{
"bar": "some value",
"baz": null
}
into Foo instance and then serialise it back to JSON, I get
{
"bar": "some value",
"baz": null
}
and if I unserialize partial JSON without "baz"
{
"bar": "some value"
}
I get again a partial JSON without "baz"
{
"bar": "some value"
}
This is not possible unless you store information about which fields were present in the original JSON objects. For this purpose, you could use a wrapper around Foo which contains a Foo plus this addtional info. Below is an example.
Note: this is pseudocode. The method and class names are part from the Gson library and part invented by me on the fly, but you get the idea. I think it shouldn't be difficult to translate this using the classes of Jackson.
class DeserializedFoo {
private Foo foo;
private Set<String> includedFields = new HashSet<>();
private DeserializedFoo(){
}
public static class DeSerializer implements JsonDeserializer<DeserializedFoo> {
#Override
public DeserializedFoo deserialize(JsonElement je) {
DeserializedFoo dsFoo = new DeserializedFoo();
dsFoo.foo = parse(je);
for(JsonElement prop : je.elements()){
includedFields.add(prop.getName());
}
return dsFoo;
}
}
public static class Serializer implements JsonSerializer<DeserializedFoo> {
#Override
public JsonElement serialize(DeserializedFoo dsFoo) {
JsonElement jsonFoo = serialize(dsFoo.foo);
// Leave only fields that were present in the JSON
// element from which this was deserialized.
Iterable it = jsonFoo.elements().iterable();
while(it.hasNext()){
JsonElement prop = it.next();
if(!includedFields.contains(prop.getName()){
it.remove();
}
}
return jsonFoo;
}
}
}
You could of course use inheritance instead of a wrapper, e.g. by defining class DeserilizedFoo extends Foo and adding the includedFields field. Each approach has its benefits and drawbacks. It's up to you to decide which one fits your situation best.
You can annotated your class with #JsonInclude(Include.NON_DEFAULT) and
set the default value for baz property to a magic string which would indicate that the value should not be present in the JSON.
Here is an example:
public class JacksonIncludeNull {
final static String JSON1 = "{\n" +
" \"bar\": \"some value\",\n" +
" \"baz\": null\n" +
"}";
final static String JSON2 = "{\n" +
" \"bar\": \"some value\"\n" +
"}";
#JsonInclude(JsonInclude.Include.NON_DEFAULT)
static class Foo {
public String bar;
public String baz = "##default";
#Override
public String toString() {
return "Foo{" +
"bar='" + bar + '\'' +
", baz='" + baz + '\'' +
'}';
}
}
public static void main(String[] args) throws IOException {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new GuavaModule());
final Foo foo1 = mapper.readValue(JSON1, Foo.class);
System.out.println(JSON1);
System.out.println("Object: " + foo1);
System.out.println("Serialize: " + mapper.writeValueAsString(foo1));
System.out.println();
final Foo foo2 = mapper.readValue(JSON2, Foo.class);
System.out.println(JSON2);
System.out.println("Object: " + foo2);
System.out.println("Serialize: " + mapper.writeValueAsString(foo2));
}
}
Output:
{
"bar": "some value",
"baz": null
}
Object: Foo{bar='some value', baz='null'}
Serialize: {"bar":"some value","baz":null}
{
"bar": "some value"
}
Object: Foo{bar='some value', baz='##default'}
Serialize: {"bar":"some value"}
I am very new to Java. I have some classes Site, Instances, CloudInstance. Class Site has an attribute instances and class CloudInstance inherits class Instance. They are as follows-
public class Site extends BaseEntity {
private String siteName;
List<Instance> instances = Lists.newArrayList();
}
public class Instance extends BaseEntity {
private String instanceId;
private String name;
}
public class CloudInstance extends Instance {
private String availabilityZone;
private String instanceType
}
I am deserializing json string as follows -
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = new ObjectMapper();
BaseEntity obj = null;
obj = (BaseEntity) mapper.readValue(jsonStr, Site.class);
It works fine if my jsonStr does not contain fields of class 'CloudInstance' and contains field instance with Instance class's fields.
Problem - Now i want to deserialize the jsonStr which includes 'CloudInstance' classe's fiels as well as the part of 'instances' field of class 'Site'. Ex jsonStr is as follows -
{
"id": null,
"siteName": "demo",
"instances": [
{
"instanceId": "i-8c2ee5fc",
"name": "some-node",
"availabilityZone": "some-zone",
"instanceType": "t1.micro"
}]
}
For the above jsonStr i get following error
error: Unrecognized field \"availabilityZone\" and error: Unrecognized field \"instanceType\"
With lots of if else and dirty code i can get the obj of Site including above fields. But i want to implement clean solution for this.
Is there any library which can do this? Any help id valuable. Please help..!!
Thanks in advance.
What you are trying to achieve is called polymorphic deserialization. Your example fails because Jackson needs to know what instance type should be constructed from JSON and placed to the list of instances. Please refer to this wiki page for detailed explanation.
I have modified you example to demonstrate how it could work. I've added the instance type information in the #type field in the JSON representation. Also I've made all the classes immutable using constructors annotated with the #JsonCreator annotation to create instances.
public class JacksonPolymorphism {
public static class BaseEntity {
private final String id;
protected BaseEntity(String id) {
this.id = id;
}
}
public static class Site extends BaseEntity {
private final String siteName;
private final List<Instance> instances;
#JsonCreator
public Site(#JsonProperty("id") String id,
#JsonProperty("siteName") String siteName,
#JsonProperty("instances") List<Instance> instances) {
super(id);
this.siteName = siteName;
this.instances = instances;
}
#Override
public String toString() {
return "Site{" +
"siteName='" + siteName + '\'' +
", instances=" + instances +
'}';
}
}
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "#type")
#JsonTypeName(value = "simple")
public static class Instance extends BaseEntity {
private final String name;
#JsonCreator
public Instance(#JsonProperty("instanceId") String id,
#JsonProperty("name") String name) {
super(id);
this.name = name;
}
#Override
public String toString() {
return "Instance{" +
"name='" + name + '\'' +
'}';
}
}
#JsonTypeName("cloud")
public static class CloudInstance extends Instance {
private final String availabilityZone;
private final String instanceType;
public CloudInstance(#JsonProperty("instanceId") String id,
#JsonProperty("name") String name,
#JsonProperty("availabilityZone") String availabilityZone,
#JsonProperty("instanceType") String instanceType) {
super(id, name);
this.availabilityZone = availabilityZone;
this.instanceType = instanceType;
}
#Override
public String toString() {
return "CloudInstance{" +
"availabilityZone='" + availabilityZone + '\'' +
", instanceType='" + instanceType + '\'' +
'}';
}
}
public static final String JSON = "{\n" +
" \"id\": null,\n" +
" \"siteName\": \"demo\",\n" +
" \"instances\": [\n" +
" {\n" +
" \"#type\": \"cloud\",\n" +
" \"instanceId\": \"i-8c2ee5fc\",\n" +
" \"name\": \"some-node\",\n" +
" \"availabilityZone\": \"some-zone\",\n" +
" \"instanceType\": \"t1.micro\" \n" +
" }," +
" {\n" +
" \"#type\": \"simple\",\n" +
" \"instanceId\": \"ABC\",\n" +
" \"name\": \"FGF\"\n" +
" }]" +
" }";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.registerSubtypes(CloudInstance.class);
System.out.println(mapper.readValue(JSON, Site.class));
}
}
Output:
Site{siteName='demo', instances=[CloudInstance{availabilityZone='some-zone', instanceType='t1.micro'}, Instance{name='FGF'}]}
I always had problems to deserialize JSON that contains List<...> objects with Jackson, so try to deserialize with Gson:
https://code.google.com/p/google-gson/
Take a look at the documentation in the methods fromJson and toJson.
I hope that can help,
Best regards
Never had consistent luck with Jackson or Gson, try Flex JSON instead:
JSONSerializer ser = new JSONSerializer();
String json = ser.deepSerialize(yourObject);
JSONDeserializer<YourMainType> der = new JSONDeserializer<YourMainType>();
YourMainType mainType = der.deserialize(json);
For this to work, all classes subject to serialization/deserialization must expose getters/setters consistent with Java Beans convention.
You can used GSON Library for de-serialize your Json into your class object.
There is function gson.fromJson(JSON String) which convert json string to class object.
Here is Sample code :
Gson json = new Gson();
Site site = json.fromJson(jsonStr, Site.class);
But in your code you have replace
List<Instance> instances = Lists.newArrayList();
this line in class Site with
List<CloudInstance> instances = new ArrayList<CloudInstance>();
Because your CloudInstance class extend Instance it means CloudInstance class include member of Instance class. As per json you need to do this to cast directly into class object.
May this will help you.