0

I'm not sure how to deserialize array containing plain strings.I'm trying to parse the following JSON

 { "state":"RT", "testMethod":"electronic", "testElements":[ { "testId":[ "UT_ITXref", "Fed_ITXref" ] }, "testStartDate", "testEndDate", "testDueDate" ] } 

I'm getting the following error:

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.test.rules.model.TestElements: no String-argument constructor/factory method to deserialize from String value ('testStartDate') at [Source: {"state":"RT","testMethod":"electronic","testElements":[{"testId":["UT_ITXref","Fed_ITXref"]},"testStartDate","testEndDate","testDueDate"}]}; line: 1, column: 247] (through reference chain: com.test.rules.model.TestRules["testElements"]->java.lang.Object[][1]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270) at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456) at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1012) at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:370) at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:315) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1282) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:159) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:150) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:196) at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:20) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:511) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:396) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1198) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:314) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148) at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1626) at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1220) 

Here is what I did , I used @JsonCreator annotation to deserialize

public class TestRules { private String state; private String testMethod; private TestElements[] testElements; @JsonCreator public TaxRules( @JsonProperty("state") String state, @JsonProperty("testMethod") String testMethod, @JsonProperty("testElements") TestElements[] testElements ) { this.state = state; this.testMethod = testMethod; this.testElements = testElements; } } public class TestElements { private List<String> testId; private List<String> elements; public List<String> getElements() { return elements; } public void setElements(List<String> elements) { this.elements = elements; } public List<String> getTestId() { return testId; } public void setTestId(List<String> testId) { this.testId = testId; } } 

Should I write custom deserializer or Is there any way that I can use the jackson API for this. Any suggestions would be appreciated.

4
  • 3
    json seems to be invalid. Are you sure testStartDate, testEndDate etc have no values? Commented Feb 21, 2017 at 22:30
  • 1
    either the json is invalid or the classes representing the json is invalid. The json is perfectly compliant with the json spec; but looks like the testElements is a mixture of objects and strings in the json, but the pojos expect only objects of a certain shape Commented Feb 21, 2017 at 22:37
  • You'll probably need to make a custom serializer if your json is correct. stackoverflow.com/questions/40915356/… has a similar situation but with two different object types Commented Feb 21, 2017 at 22:42
  • @Atreys Thanks, the link you provided is array of Map , but mine is different. Is there any way I can map plain strings to elements (in TestElements) Commented Feb 21, 2017 at 22:57

2 Answers 2

1

Actually errors tells something.

JSON parser found that for testElements property there is an Array of Objects, but your Json file has mixed content.

first element is an object (I assume it is TestElement class). Then parser creates that object with empty constructor and calls appropriate setters for its properties. but...

second,third and forth elements are String, so error says that parser tries to find constrictor with String as argument.

So, you may try to make that constructor in TestElement class and see will it work or not... Do not forget to keep empty constructor as well.

I cannot guarantee it will work but, at least error says that.

BTW are you sure your Json object is correct? but not something like that?

{ "state":"RT", "testMethod":"electronic", "testElements":[ { "testId":[ "UT_ITXref", "Fed_ITXref" ] }], "testStartDate":"01-01-2017", "testEndDate":"01-02-2017", "testDueDate":"01-03-2017" } 

I'm a little confused because StartDate, EndDate, DueDate semantically look more like test attributes, not as elements in testElements array

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I'll try with string argument constructor. The JSON that i provided is a valid one. I need to pass this json to another service to retrieve the values of testElements.
Glad to hear it. It is new to me as well, I'll keep in mind that it is a possible way with Jackson.
0
{ "state": "RT", "testMethod": "electronic", "testElements": [ { "testId": [ "UT_ITXref", // <-- this object is deserialized just fine "Fed_ITXref" ] }, "testStartDate", // <-- this is where the error is happening "testEndDate", "testDueDate" ] } 

Did you intend the json to be interpreted as if it looked like the following?

{ "state": "RT", "testMethod": "electronic", "testElements": [ { "testId": [ "UT_ITXref", "Fed_ITXref" ] }, { testId: [ "testStartDate" ] }, { testId: [ "testEndDate" ] }, { testId: [ "testDueDate" ] } ] } 

If so, you'll need to make a custom deserializer to detect whether the element in the array is an object or a string. If it's a string, you'll probably want to construct the TestElement yourself.

1 Comment

Thanks for your time . Unfortunately it will not work for me. I gave you the sample json. Actual JSON has more elements of different objects (like testId) and strings. Would try the String argument constructor as suggested by Vadim , if it works fine, otherwise I would go for custom serializer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.