Deserializing JSON with Jackson - Why JsonMappingException “No suitable constructor”?

前端 未结 5 1810
眼角桃花
眼角桃花 2020-12-16 10:39

I have a problem deserializing a JSON string using Jackson (but I have no problem serializing an object to JSON).

Below I present the classes I use. The problem come

相关标签:
5条回答
  • 2020-12-16 11:23

    I was facing the issue and none of the answers worked for me. it seems the exception thrown is very generic one and is thrown for n number of causes. So one fix may not work for everyone. My case: we have a json response in which creditcard is a complex type but optional. when there is no creditcard data, we were getting an empty string in response:

    "creditcard":""

    But Credit card is a complex type for us:

    <xs:element name="CC" minOccurs="0">
                                    <xs:complexType>
                                        <xs:sequence>
                                            <xs:element name="aaa" type="xs:string" minOccurs="0"/>
                                            <xs:element name="bbb" type="xs:string" minOccurs="0"/>
                                            <xs:element name="ccc" type="xs:string" minOccurs="0"/>
                                        </xs:sequence>
                                    </xs:complexType>
                                </xs:element>
    

    We figured out, if there is no creditcard data, we should have something like this in json response:

    "creditcard":{}

    and not "creditcard":""

    it fixed this issue.

    0 讨论(0)
  • 2020-12-16 11:24

    Thumb Rule: Add a default constructor for each class you used as a mapping class. You missed this and issue arise!

    Simply add a default constructor and it should work.

    0 讨论(0)
  • 2020-12-16 11:35

    In this case, you could add @JsonCreator annotation to constructor. There are two ways it could be done:

    • If you only add that annotation, then the whole matching JSON is first bound to type of the only argument (`DataPacket'). I assume you do not want to do that.
    • If you also add @JsonProperty annotation before the argument, then JSON property matching that name is passed to constructor (annotation is mandatory because Java byte code does NOT contain name of method or constructor arguments) -- I suspect you want @JsonProperty("SubPacket")

    This works if necessary information for constructor comes from JSON. If not, you do need to add alternate no-arg constructor.

    By the way, the error message does sound wrong in this case. It should only be given if JSON data matching expected value if a JSON String.

    0 讨论(0)
  • 2020-12-16 11:37

    The error messages says it all, your ProtocolContainer does not have a default constructor so Jackson is unable to create an instance of it. (Since the only current way of creating a ProtocolContainer is by passing in a DataPacket.)

    0 讨论(0)
  • 2020-12-16 11:37

    Another possibility if you use Lombok! I haven't found out the reason.

    @Getter
    @NoArgsConstructor
    @FieldDefaults(level = AccessLevel.PRIVATE)
    public Car implements Serializable {
       Map<String, Object> basicInfo;
       CarEnums.TypeEnum type;
       List<Maintenance> maintenances;
       public void addMaintenance(Maintenance m) {
          // initialize if null
          maintenances.add(m);
       }
    
       // must be static or jackson throws "inner class cannot be static" exception.  Yes you see it right. 
       public static class Maintenance { 
          private Long id;
          public class Maintenance(Long id) { // constructor causes the exception
             this.id = id;
          }
       }
       ...
    }
    

    If lombok constructor annotation is used at outer class, the inner class even if one writes all args constructor manually, it still complains the constructor cannot be found. If you use @AllArgsConstructor on Maintenance instead of writing your own, jackson would deserialise successfully. I got the same experience today, adding @AllArgsConstructor solves it.

    0 讨论(0)
提交回复
热议问题