简体   繁体   English

杰克逊:如何反序列化我自己课程的实例字段

[英]Jackson: How to deserialize instance field of my own class

I'm writing RESTful web service for my android app. 我正在为我的Android应用程序编写RESTful Web服务。 I have my POJO class named ServiceResponse: 我有一个名为ServiceResponse的POJO类:

private int responseCode;
private String objectType;
private ArrayList<Object> data;

public int getResponseCode() {
    return responseCode;
}

public void setResponseCode(int responseCode) {
    this.responseCode = responseCode;
}

public ArrayList<Object> getData() {
    return data;
}

public void setArrayData(ArrayList<Object> data) {
    this.data = data;
}

public void setData(Object data) {
    if(this.data == null) this.data = new ArrayList<Object>();
    this.data.add(data);
}

public String getObjectType() {
    return objectType;
}

public void setObjectType(String objectType) {
    this.objectType = objectType;
}

It's parsed to JSON using Jackson, example here: http://pastebin.com/pu8792a1 There will be many classes passed using this arraylist. 它使用杰克逊(Jackson)解析为JSON,例如: http : //pastebin.com/pu8792a1将有许多使用此数组列表传递的类。 My question is, how do I make it ServiceResponse object again from the JSON? 我的问题是,如何从JSON重新使其成为ServiceResponse对象?

{
  "responseCode" : 2,
  "objectType" : "com.example.User",
  "data" : [ {
    "name" : "name",
    "password" : "pass",
    "email" : "mail@gmail.com",
    "device" : "ABC",
    "level" : 10,
    "gold" : 82,
    "delois" : 0,
    "uranium" : 0,
    "attack" : 5,
    "speed" : 5,
    "armor" : 5,
    "controllability" : 5,
    "exp" : 100,
    "hp" : 100,
    "hpMax" : 300,
    "deuter" : 21,
    "deuterMax" : 120,
    "research" : 1413360596907,
    "id" : 1
  } ]

I tried: (skipped try & catch) 我尝试过:(跳过尝试并捕获)

    ObjectMapper mapper = new ObjectMapper();
    ServiceResponse response;
    response = mapper.readValue(output, ServiceResponse.class);

    User user =  (User) ( response.getData().get(0) );
    System.out.println(user.toString());

but I got ClassCastException: java.util.ArrayList cannot be cast into com.example.User 但是我得到了ClassCastException:java.util.ArrayList无法转换为com.example.User

A couple problems: 几个问题:

Problem 1: 问题一:

"data" : [ {
  "name" : "name",
  "password" : "pass"
  ...
} ]

private ArrayList<Object> data;

Since you define the type of the list as Object the parser doesn't know to map it to a User type, so it will map it to an array of LinkedHashMap . 由于您将列表的类型定义为Object因此解析器不知道将其映射为User类型,因此它将其映射为LinkedHashMap的数组。 So basically you're left with ArrayList<LinkedHashMap> data . 所以基本上您只剩下ArrayList<LinkedHashMap> data Change all the Object to User . 将所有Object更改为User

Problem 2: 问题2:

private ArrayList<User> data;
...
public void setData(User data) {
    if (this.data == null) {
        this.data = new ArrayList<User>();
    }
    this.data.add(data);
}

The parser will look for JavaBean properties that follow JavaBean naming convention ie property / setProperty / getProperty . 解析器将查找遵循JavaBean命名约定的JavaBean属性,即property / setProperty / getProperty In your case the parser thinks the setData is a setter to set the value of the data field. 在您的情况下,解析器认为setData是用于设置 data字段值的设置器。 As a setter , it will expect an ArrayList<User> and not a User as the argument. 作为设置器 ,它将以ArrayList<User>而不是User作为参数。 So better to change the name to something like addUser(User user) . 因此最好将名称更改为类似addUser(User user) While you're at it, you should change the name of setArrayData to follow the name convention also. 在使用它时,您应该更改setArrayData的名称以也遵循名称约定。

public void setData(ArrayList<User> data) {
    this.data = data;
}

public void addUser(User data) {
    if (this.data == null) {
        this.data = new ArrayList<User>();
    }
    this.data.add(data);
}

Making these few changes should get it working (tested). 进行这些更改后,它应该可以正常工作(经过测试)。


UPDATE: Problem 1 is actually not a problem 更新:问题1实际上不是问题

I know I could make it work if I used User instead of Object, but I'd like to send different objects in data array (sometimes it would be User, other time, for example Item). 我知道如果使用User而不是Object可以使它工作,但是我想在数据数组中发送不同的对象(有时是User,其他时候是Item)。 Is there a way to do it? 有办法吗? Here They say I can use this: POJO pojo = mapper.convertValue(singleObject, POJO.class); 在这里,他们说我可以使用: POJO pojo = mapper.convertValue(singleObject, POJO.class); To convert from LinkedHashMap to my object, but when I try it: User user = mapper.convertValue(response.getData().get(0), User.class); 要将LinkedHashMap转换为我的对象,但是在尝试时:User user = mapper.convertValue(response.getData()。get(0),User.class); User is still null 用户仍然为空

As the OP brought to my attention, we can convert the map the parser created by using ObjectMapper.convertValue( map , User.class); 当OP引起我注意时,我们可以使用ObjectMapper.convertValue( map , User.class);转换解析器创建的ObjectMapper.convertValue( map , User.class); . Not sure why the OP is getting null, but when I tested, changing the User types back to Object type, it works fine 不知道为什么OP为空,但是当我测试时,将User类型改回Object类型,就可以正常工作

public class Test {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        InputStream is = Test.class.getResourceAsStream("test.json");
        ServiceResponse response = mapper.readValue(is, ServiceResponse.class);
        User user = (User) (mapper.convertValue(response.getData().get(0), User.class));
        System.out.println(user.toString());
        is.close();
    }
}

Result test.json.User@366e2eef 结果test.json.User@366e2eef


UPDATE 2: 更新2:

The OP wants to use the String objectType to convert the the map by type: OP希望使用String objectType通过类型转换地图:

ServiceResponse response = ...
String objectType = response.getObjectType();
Class clazz = Class.forName(objectType);      // catch exception
ArrayList user = (mapper.convertValue(response.getData(), 
            TypeFactory.defaultInstance().constructCollectionType(
                    ArrayList.class, clazz)));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM