How to create this JSONObject using java? - java

How do I create the following json using java classes and lombok's builder?
I used some json to pojo tool and created 2 classes: Entry.java and Testplan.java, added a method to convert String to json and managed to get a json object: {"suite_id":99,"name":"Some random name"}
I don't understand how to create one that would look like this:
{
"name": "System test",
"entries": [
{
"suite_id": 1,
"name": "Custom run name"
},
{
"suite_id": 1,
"include_all": false,
"case_ids": [
1,
2,
3,
5
]
}
]
}
Testplan.java
#Data
#Builder
public class Testplan {
#JsonProperty("name")
public String name;
#JsonProperty("entries")
public List<Entry> entries = null;
}
Entry.java
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Entry {
#JsonProperty("suite_id")
public Integer suiteId;
#JsonProperty("name")
public String name;
#JsonProperty("include_all")
public Boolean includeAll;
#JsonProperty("case_ids")
public List<Integer> caseIds = null;
}
I convert String to json using this:
public <U> String toJson(U request) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
return mapper.writeValueAsString(request);
}
Here's how I started creating the object and got stuck:
public static Entry getRequestTemplate() {
Entry entry = new Entry();
entry.setName("Here's some name");
entry.setSuiteId(16);
return entry;
}
To see what's happening I added this:
#Test
public void showJson() throws JsonProcessingException {
String json = toJson(getRequestTemplate());
System.out.println(json);
}
I expect to have have to combine these two classes and create a list of case_ids but can't wrap my head around it.

This worked:
Created a new method of Testplan:
public Testplan kek2() {
Testplan testplan = Testplan.builder()
.name("System test")
.entries(Lists.newArrayList(Entry.builder()
.name("Custom run name")
.suiteId(1)
.includeAll(false)
.caseIds(new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)))
.build()))
.build();
System.out.println(testplan);
return testplan;
}
and then used this method to convert pojo to json:
protected <U> String toJson(U request) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(request);
}

Related

How to parse a json with dynamic property name in java?

I need to consume and parse incoming json from a CRM system in my code. I used RestTemplate to do it. So the response from the CRM system looks like below.
{ "GvyArEFkg6JX6wI": {
"entityId": "GvyArEFkg6JX6wI",
"mergePolicy": {
"id": "9245a39d-fe1a-4b33-acab-9bc5cbabf37c"
}
}
}
Now the problem is the property name ("GvyArEFkg6JX6wI" in this case) in dynamic and in the next response it would be another string. In this case, how can I parse this json as this is not fixed? I tried using jsonGetter but it only wraps it around another block and still does not resolve the problem of parsing the response.
AdobeResponseDto.class
#Builder
#ToString
#AllArgsConstructor
#JsonInclude(JsonInclude.Include.NON_NULL)
#NoArgsConstructor
public class AdobeResponseDto {
public Map<String, AdobeResponseFinal> adobeResponseWrapper = new HashMap<>();
#JsonAnySetter
public void setAdobeResponseWrapper(String name, AdobeResponseFinal value) {
adobeResponseWrapper.put(name, value);
}
#JsonAnyGetter
public Map<String, AdobeResponseFinal> getAdobeResponseWrapper() {
return adobeResponseWrapper;
}
}
AdobeResponseFinal.class
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class AdobeResponseFinal {
public String entityId;
public MergePolicy mergePolicy;
}
I am calling the service like this:
final ResponseEntity<AdobeResponseDto> finalResponse;
finalResponse = aepClient.exchange(uri,HttpMethod.GET,entity,AdobeResponseDto.class);
final AdobeResponseDto body = finalResponse.getBody();
if(ObjectUtils.isNotEmpty(body)){
return body;
}
But in this way, the response I am getting is
{
"adobeResponseWrapper": {
"GvyArEFkg6JX6wI": {
"entityId": "GvyArEFkg6JX6wI",
"mergePolicy": {
"id": "9245a39d-fe1a-4b33-acab-9bc5cbabf37c"
}
}
If you just want to get the value of dynamic field name (e.g., "GvyArEFkg6JX6wI" in your case), you can just deserialize the response body to a Map and then traverse its value as follows:
ResponseEntity<String> finalResponse = aepClient.exchange(uri, HttpMethod.GET, entity, String.class);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> result = objectMapper.readValue(finalResponse.getBody(), Map.class);
result.values().forEach(System.out::println);
Console output:
{entityId=GvyArEFkg6JX6wI, mergePolicy={id=9245a39d-fe1a-4b33-acab-9bc5cbabf37c}}
And if you want to deserialize the response body to your DTO (I assume that there is only ONE root-level property), you can modify the DTO like:
public class AdobeResponseDto {
private AdobeResponseFinal adobeResponseFinal;
#JsonAnySetter
public void setAdobeResponseFinal(String name, AdobeResponseFinal value) {
adobeResponseFinal = value;
}
#JsonAnyGetter
public AdobeResponseFinal getAdobeResponseFinal() {
return adobeResponseFinal;
}
}
Then you can get similar result as follows:
ResponseEntity<String> finalResponse = aepClient.exchange(uri, HttpMethod.GET, entity, String.class);
AdobeResponseDto adobeResponseDto = objectMapper.readValue(finalResponse.getBody(), AdobeResponseDto.class);
System.out.println(adobeResponseDto.getAdobeResponseFinal().toString());
Console output:
AdobeResponseFinal{entityId='GvyArEFkg6JX6wI', mergePolicy=MergePolicy{id='9245a39d-fe1a-4b33-acab-9bc5cbabf37c'}}

Jackson serialization of immutable value class with optional fields

I am using Immutables library (https://immutables.github.io).
My class looks as follows:
package com.abc.myservice.data.models;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;
import java.util.Map;
import java.util.Optional;
#Value.Immutable
#JsonSerialize(as = ImmutableMyEntityModel.class)
#JsonDeserialize(as = ImmutableMyEntityModel.class)
public interface MyEntityModel {
String myEntityId();
String status();
Optional<Integer> count();
Optional<Integer> version();
Optional<Map<String, String>> attributes();
}
I build the immutable class object with:
ImmutableMyEntityModel.builder()
.myEntityId("some-id")
.status("some-status")
.count(Optional.of(10))
.build()
And my output is:
{
"MyEntityId": "some-id",
"status": "some-status",
"count": {
"present": true
},
"version": {
"present": false
},
"attributes": {
"present": false
}
}
Instead what I would like to see is:
{
"MyEntityId": "some-id",
"status": "some-status",
"count": 10
}
How can I make it work like that?
Use the jackson-datatype-jdk8 module so that Jackson properly understands the java.util.Optional type - a pretty good explanation is in this article.
Add jackson-datatype-jdk8 library to your project/classpath, which contains a Jackson module that allows Jackson to properly understand Optionals.
When creating an ObjectMapper, register the Jdk8Module:
ObjectMapper om = new ObjectMapper();
om.registerModule(new Jdk8Module());
Optionally, add #JsonIgnoreProperties(ignoreUnknown = true) to properties or the class itself to avoid serializing Optional.empty() to null values and instead ignore the property completely.
Full example:
public class JacksonOptionalTest
{
public static void main(String... args)
throws Exception
{
ObjectMapper om = new ObjectMapper();
om.registerModule(new Jdk8Module());
Thing thing = new Thing();
thing.name = "John Smith";
thing.count = Optional.of(12);
String s = om.writeValueAsString(thing);
System.out.println(s);
}
#JsonInclude(Include.NON_ABSENT)
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Thing
{
public String name;
public Optional<Integer> count = Optional.empty();
public Optional<Integer> version = Optional.empty();
}
}
The output of this is {"name":"John Smith","count":12}.

Jackson deserialization bellow JSON property

I want to fetchMultiple(ParameterizedTypeReference<List<T>> responseType) for a given List<T>, in this case, I want to get directly a List<Account> but I am getting an error because the list of accounts is encapsulated in another object, as shown below:
{
"accounts": [
{
"accountUid": "c75deb59-5d52-4a23-af7b-fce29927ce9d",
"defaultCategory": "b4189da5-7688-42d0-86e3-14ae9031e01d",
"currency": "GBP",
"createdAt": "2020-08-05T16:50:50.536Z"
}
]
}
There is some Jackson annotation to filter this somehow in order to be processed like this:
[
{
"accountUid": "c75deb59-5d52-4a23-af7b-fce29927ce9d",
"defaultCategory": "b4189da5-7688-42d0-86e3-14ae9031e01d",
"currency": "GBP",
"createdAt": "2020-08-05T16:50:50.536Z"
}
]
POJO
#Data
public class Account {
private String accountUid;
private String defaultCategory;
private String currency;
private String createdAt;
}
RestRequestTemplate.java
public List<T> fetchMultiple(ParameterizedTypeReference<List<T>> responseType) {
return new RestTemplate().exchange(this.url, this.httpMethod, this.request, responseType).getBody();
}
AccountsServiceImpl.java
public List<Account> getAccounts() {
RestRequestTemplate restRequestTemplate = new RestRequestTemplate(GET_ACCOUNTS, HttpMethod.GET, Collections.EMPTY_MAP);
return restRequestTemplate.fetchMultiple(new ParameterizedTypeReference<List<Account>>() {});
}
There is indeed an annotation to ignore the root object. It is called #JsonUnwrapped. Annotate your method with that annotation and your json should be without the root object.

Jackson Mixin not working in Pojo to json

My target is xml to Pojo and Pojo to json. I already did xml to pojo using jaxb. Now I am trying pojo to json using jackson Jaxb. Where I am getting the following json which produce JXBElement class fileds in json like following.
{
"name" : "{http://xxx.xx.xx.xx.xx.xx.xx}CompositeResponse",
"declaredType" : "xxx.xx.xx.xx.xx.xx.xxCompositeResponseType",
"scope" : "javax.xml.bind.JAXBElement$GlobalScope",
"value" : {
"CompositeIndividualResponse" : [ {
"ResponseMetadata" : {
"ResponseCode" : "HS000000",
"ResponseDescriptionText" : "Success"
}
} ]
},
"nil" : false,
"globalScope" : true,
"typeSubstituted" : false
}
How Can I removed name, declaredType,scope,nil, globalScope,typeSubstituted ang get the following json
{
"CompositeResponse":
{
"CompositeIndividualResponse" : [ {
"ResponseMetadata" : {
"ResponseCode" : "HS000000",
"ResponseDescriptionText" : "Success"
}
} ]
}
}
I was looking this post but this does not work for me.
The following code I have tried for jackson mixin.
public class Main {
public static interface JAXBElementMixinT {
#JsonValue
Object getValue();
}
public static void main(String[] args) throws XMLStreamException, IOException {
ObjectMapper mapper = new ObjectMapper();
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(mapper.getTypeFactory());
mapper.setAnnotationIntrospector(introspector );
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.addMixIn(JAXBElement.class, JAXBElementMixinT.class);
String result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee);
System.out.println(result);
}
}
I also tried with following code but no luck.
public abstract class JAXBElementMixIn {
#JsonIgnore abstract String getScope();
#JsonIgnore abstract boolean isNil();
#JsonIgnore abstract boolean isGlobalScope();
#JsonIgnore abstract boolean isTypeSubstituted();
#JsonIgnore abstract Class getDeclaredType();
}
Can anyone help me where I am wrong and what to do thanks.
I just faced this issue this week in fact and solved it by removing the
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(mapper.getTypeFactory());
mapper.setAnnotationIntrospector(introspector );
Piece. I haven't looked back into how to add that back yet, but that let the rest of the code you have work for me correctly and I'm no longer seeing the JAXBElement wrapper.
Finally I am able to solve the problem. According #Ryan answer I donot need the following code:
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(mapper.getTypeFactory());
mapper.setAnnotationIntrospector(introspector );
But I have to add the JaxbAnnotationModule module = new JaxbAnnotationModule(); mapper.registerModule(module) otherwise jackson will produce links and metadata for every element. The complete code is following
public class Main {
public static interface JAXBElementMixinT {
#JsonValue
Object getValue();
}
public static void main(String[] args) throws XMLStreamException, IOException {
ObjectMapper mapper = new ObjectMapper();
JaxbAnnotationModule module = new JaxbAnnotationModule();
mapper.registerModule(module)
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.addMixIn(JAXBElement.class, JAXBElementMixinT.class);
String result = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(employee);
System.out.println(result);
}
}

Convert JSON to Java Object, how to parse BadgerFish convention with Jackson

Using an API I receive JSON like this (which are now saved to file):
[{
"LEI": {
"$": "549300Q82NZ9NYNMZT63"
},
"Entity": {
"LegalName": {
"$": "United Nerds in Collaboration of Random Nerdiness AB"
},
"LegalAddress": {
"Line1": {
"$": "BOX 155"
},
"City": {
"$": "Alingsas"
},
"Region": {
"$": "SE-O"
},
"Country": {
"$": "SE"
},
"PostalCode": {
"$": "44123"
}
},
"HeadquartersAddress": {
"Line1": {
"$": "BOX 155"
},
"City": {
"$": "Alingsas"
},
"Region": {
"$": "SE-O"
},
"Country": {
"$": "SE"
},
"PostalCode": {
"$": "44123"
}
},
"BusinessRegisterEntityID": {
"#register": "SE001",
"$": "5568557184"
},
"LegalJurisdiction": {
"$": "SE"
},
"LegalForm": {
"$": "PRIVATA AKTIEBOLAG"
},
"EntityStatus": {
"$": "ACTIVE"
}
},
"Registration": {
"InitialRegistrationDate": {
"$": "2016-06-23T01:48:45.025Z"
},
"LastUpdateDate": {
"$": "2016-06-23T01:48:44.945Z"
},
"RegistrationStatus": {
"$": "ISSUED"
},
"NextRenewalDate": {
"$": "2017-06-21T06:32:03.821Z"
},
"ManagingLOU": {
"$": "EVK05KS7XY1DEII3R011"
},
"ValidationSources": {
"$": "PARTIALLY_CORROBORATED"
}
}
}]
I would like to get Java Object out of these. I have already created the Java Objects out of an xsd file provided. The code I'm running is:
public static void toJava() {
ObjectMapper mapper = new ObjectMapper();
try {
File json = new File("C:\\temp\\JSON.json");
LEIRecordType[] type = mapper.readValue(json, LEIRecordType[].class);
} catch (JsonEOFException ex) {
ex.printStackTrace();
} catch (JsonMappingException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
Which creates these Exceptions:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "LEI" (class org.leiroc.data.schema.leidata._2014.LEIRecordType), not marked as ignorable (5 known properties: "lei", "registration", "entity", "nextVersion", "extension"])
at [Source: (File); line: 3, column: 14] (through reference chain: java.lang.Object[][0]->org.leiroc.data.schema.leidata._2014.LEIRecordType["LEI"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:60)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:822)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1152)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1567)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1545)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2890)
at Test.JSONParser.toJava(JSONParser.java:38)
at Test.JSONParser.main(JSONParser.java:29)
LEIRecordType looks like this:
package org.leiroc.data.schema.leidata._2014;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "LEIRecordType", propOrder = {"lei", "entity", "registration", "nextVersion", "extension"})
public class LEIRecordType {
#XmlElement(name = "LEI", required = true)
protected String lei;
#XmlElement(name = "Entity", required = true)
protected EntityType entity;
#XmlElement(name = "Registration", required = true)
protected RegistrationType registration;
#XmlElement(name = "NextVersion")
protected LEIRecordNextVersionType nextVersion;
#XmlElement(name = "Extension")
protected ExtensionType extension;
public String getLEI() {
return this.lei;
}
public void setLEI(String paramString) {
this.lei = paramString;
}
public EntityType getEntity() {
return this.entity;
}
public void setEntity(EntityType paramEntityType) {
this.entity = paramEntityType;
}
public RegistrationType getRegistration() {
return this.registration;
}
public void setRegistration(RegistrationType paramRegistrationType) {
this.registration = paramRegistrationType;
}
public LEIRecordNextVersionType getNextVersion() {
return this.nextVersion;
}
public void setNextVersion(LEIRecordNextVersionType paramLEIRecordNextVersionType) {
this.nextVersion = paramLEIRecordNextVersionType;
}
public ExtensionType getExtension() {
return this.extension;
}
public void setExtension(ExtensionType paramExtensionType) {
this.extension = paramExtensionType;
}
}
I understand that the problem is that jackson is locking for an Java Object called LEI, with an variable called "$". But there is none. The organisations help service says:
"The "$" object always reproduces the simple content (i.e. not the attributes, child nodes etc.) of the corresponding XML element.
The "$" object should always be typed as a JSON string where applicable."
But as I understand this is not JSON standard.
My question is: Is there any way to get jackson to parse this as LEI = "549300Q82NZ9NYNMZT63" etc. instead of and object LEI with an variable "$"?
Have been stuck on this for the better part of a day.
#UPDATE
This JSON format is apparently called "The BadgerFish convention", accoring to customer services.
As the $ object is always a String, you can create a custom deserializer for Strings that handles the BadgerFish wrapper objects.
This deserializer checks if there is a BadgerFish wrapper object around a String value and unwraps it. Normal String values are deserialized as usual.
public class BadgerFishDeserializer extends StdDeserializer<String> {
private static final long serialVersionUID = 1L;
private static final SerializedString BADGER_FISH_FIELD_NAME = new SerializedString("$");
public BadgerFishDeserializer() {
super(String.class);
}
#Override
public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
// do we have a wrapper object?
if (jp.isExpectedStartObjectToken()) {
// check if first field name is equal to '$'
if (!jp.nextFieldName(BADGER_FISH_FIELD_NAME)) {
ctxt.reportInputMismatch(String.class, "Expected BadgerFish field name '$', but got '%s'", jp.getCurrentName());
}
jp.nextValue(); // proceed to the actual value
String value = jp.getValueAsString(); // read value as string
jp.nextToken(); // consume END_OBJECT of wrapper object
return value;
}
// else: just return string value
return jp.getValueAsString();
}
}
Finally register the module on your Jackson ObjectMapper instance:
SimpleModule module = new SimpleModule();
module.addDeserializer(String.class, new BadgerFishDeserializer());
mapper.registerModule(module);
Note: If you only want some properties to be unwrapped, you could create a custom annotation and use a BeanDeserializerModifier to check for the annotation and then provide a deserializer that handles the wrapper objects.
Some food for thought:
Create annotation
Modify the deserializer to always expect wrapper objects (fail on plain Strings)
Create a DeserializerModifier
Register the DeserializerModifier on ObjectMapper
The difficult part:
public class BadgerFishDeserializerModifier extends BeanDeserializerModifier {
#Override
public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) {
Iterator<SettableBeanProperty> props = builder.getProperties();
while (props.hasNext()) {
SettableBeanProperty prop = props.next();
if (prop.getAnnotation(MyAnnotation.class) != null) {
builder.addOrReplaceProperty(prop.withValueDeserializer(new BadgerFishDeserializer()), true);
}
}
return builder;
}
}
This has been very helpful! I ended up having to do a special deserializer for both String and XMLGregorianCalendar aswell. But the problem does not stop there. BadgerFish takes the #XMLAttributes from the generated classes and sets them as #value instead of "value". As for example:
"BusinessRegisterEntityID": {
"#register": "SE001",
"$": "5568557184"
}
So is their any way to also custom the field name back to the original? Currently I now get this exception:
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "#register" (class leigen.BusinessRegisterEntityIDType), not marked as ignorable (2 known properties: "value", "register"])
at [Source: (File); line: 44, column: 27] (through reference chain: java.lang.Object[][0]->leigen.LEIRecordType["Entity"]->leigen.EntityType["BusinessRegisterEntityID"]->leigen.BusinessRegisterEntityIDType["#register"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:60)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:822)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1152)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1567)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1545)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:136)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:136)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2890)
at Test.JSONParser.toJava(JSONParser.java:47)
at Test.JSONParser.main(JSONParser.java:28)
I'm able to bypass this by putting a "ignore" (DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES )in the config like in my now current code here:
public static LEIRecordType[] toJava(File json) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(String.class, new BadgerFishStringDeserializer());
module.addDeserializer(XMLGregorianCalendar.class, new BadgerFishXMLGregorianCalendarDeserializer());
module.addDeserializer(NameType.class, new BadgerFishNameTypeDeserializer());
mapper.registerModule(module);
mapper.registerModule(new JaxbAnnotationModule()); // To be able to read JAXB annotations.
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper.readValue(json, LEIRecordType[].class);
}
But this only sets the values starting with # as null. Is there another way to solve this? Otherwise I would have to write a custom deserializer for all my generated classes, which is about 25 (and there could always be more in the next version). I have already done one for NameType, but for other example more are needed.
I think the clear solution is using #JsonProperty("$"):
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
List<LEIModel> leiList = Arrays.asList(mapper.readValue(response.toString(), LEIModel[].class));
The LEIModel class:
public class LEIModel {
#JsonProperty("Entity")
private Entity entity;
public Entity getEntity() {
return entity;
}
public void setEntity(Entity entity) {
this.entity = entity;
}
}
The Entity class:
public class Entity {
#JsonProperty("LegalName")
private LegalName legalName;
public LegalName getLegalName() {
return legalName;
}
public void setLegalName(LegalName legalName) {
this.legalName = legalName;
}
}
The LegalName class:
public class LegalName {
#JsonProperty("$")
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

Categories

Resources