用Jackson反序列化JSON - 为什么JsonMappingException"没有合适的构造函数"?

Ted*_*Ted 23 java json jackson

我在使用Jackson反序列化JSON字符串时遇到问题(但我将对象序列化为JSON没有问题).

下面我介绍我使用的课程.当我接收一个JSON字符串(一个在其他地方序列化并通过webservice检索的ProtocolContainer)并希望对其进行反序列化时,问题就出现了:

JSON字符串:

{ "DataPacketJSONString":NULL, "DataPacketType": "MyPackage.DataPackets.LoginRequestReply", "的MessageId":6604, "SenderUsername":NULL, "子分组":{ "__类型": "LoginRequestReply:#MyPackage.DataPackets","原因":"错误的传递或用户名","成功":false,"用户名":"用户1"}}

我试着像这样反序列化:

ProtocolContainer ret = ProtocolContainer.Create(jsonString);
Run Code Online (Sandbox Code Playgroud)

并且可以在下面看到在ProtocolContainer中执行的代码.例外:

org.codehaus.jackson.map.JsonMappingException:找不到类型[simple type,class MyPackage.ProtocolContainer]的合​​适构造函数:无法在[Source:java.io.]中从JSON对象实例化(需要添加/启用类型信息?). StringReader @ 4059dcb0; line:1,column:2]

我真的很感激这里的一些输入=)Thx!

ProtocolContainer.java - 封装我的"SubPackets"的容器类:

import java.io.IOException;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import MyPackage.DataPackets.*;

public class ProtocolContainer 
{
    public String SenderUsername;
    public String DataPacketType;
    public long MessageId;
    public String DataPacketJSONString;
    public DataPacket SubPacket;

    public ProtocolContainer(DataPacket dp)
    {
        DataPacketType = dp.getClass().toString().substring(6);
        SubPacket = dp;
    }

    public String toJSON()
    {
        try {
            if (SubPacket != null)
                this.DataPacketJSONString = ProtocolContainer.mapper.writeValueAsString(SubPacket);

            return ProtocolContainer.mapper.writeValueAsString(this);
        } catch (JsonGenerationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public static ObjectMapper mapper = new ObjectMapper();

    public static ProtocolContainer Create(String jsonString)
    {
        ProtocolContainer pc = null;
        try {
            pc = mapper.readValue(jsonString, ProtocolContainer.class); // error here!
        } catch (JsonParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JsonMappingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();  // Exception when deserializing
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        try 
        {
            if (pc != null && pc.DataPacketType == "LoginRequest")
                pc.SubPacket = mapper.readValue(jsonString, LoginRequest.class);
    }
        catch (JsonParseException e) 
        {
            e.printStackTrace();
        }
        catch (JsonMappingException e) 
        {
            e.printStackTrace();
        }
        catch (IOException e) 
        {
            e.printStackTrace();
        }
        return pc;
    }
}
Run Code Online (Sandbox Code Playgroud)

DataPacket.java - 我所有数据包的超类

public class DataPacket 
{

}
Run Code Online (Sandbox Code Playgroud)

LoginRequestReply.java - 一个DataPacket

package MyPackage.DataPackets;

import MyPackage.DataPacket;

public class LoginRequestReply extends DataPacket
{
    public boolean LoginOK;
    public int UserId;
}
Run Code Online (Sandbox Code Playgroud)

Ola*_*ahl 31

错误消息说明了一切,您的ProtocolContainer没有默认构造函数,因此Jackson无法创建它的实例.(因为创建ProtocolContainer的唯一当前方法是传入DataPacket.)


Sta*_*Man 15

在这种情况下,您可以@JsonCreator向构造函数添加注释.有两种方法可以做到:

  • 如果只添加该注释,那么整个匹配的JSON首先绑定到唯一参数的类型(`DataPacket').我假设你不想这样做.
  • 如果你还在@JsonProperty参数之前添加注释,那么匹配该名称的JSON属性将传递给构造函数(注释是必需的,因为Java字节代码不包含方法或构造函数参数的名称) - 我怀疑你想要@JsonProperty("SubPacket")

如果构造函数的必要信息来自JSON,则此方法有效.如果没有,则需要添加备用no-arg构造函数.

顺便说一下,在这种情况下错误消息确实是错误的.如果JSON数据与JSON字符串匹配期望值,则应该给出它.