【问题标题】:Mapping JSON data to Java POJO Class with Jackson Mapper使用 Jackson Mapper 将 JSON 数据映射到 Java POJO 类
【发布时间】:2013-09-06 10:38:57
【问题描述】:

我正在开发一个 android 应用程序,我正在尝试使用 Jackson 的 Stream 功能来处理一些 Java 数据。为此,我有几个代码示例要运行,并将解释每个示例的作用。

这是我正在使用的 JSON:

{
"users": [
    {
        "ID": "26",
        "data1": "Momonth",
        "data2": "2011-10-30 04:34:53"
    },
    {
        "ID": "45",
        "data1": "Porto",
        "data2": "2011-10-18 05:34:00"
    },
    {
        "ID": "21",
        "data1": "Tomson",
        "data2": "2011-10-12 02:44:13"
    }
],
"success": 1,
}

下面的代码是存储此数据的 POJO,因为它遍历了我的数据中的每个“用户”数组列表项:

@JsonRootName(value = "users")
public class User {

    String ID;
    String data1;
    String data2;
    ...

    public String getID() {
        return ID;
    }
    public void setID(String iD) {
        ID = iD;
    }
    public String getData1() {
        return data1;
    }
    public void setData1(String data1) {
        this.data1 = data1;
    }
    public String getData2() {
        return data2;
    }
    public void setData2(String data2) {
        this.data2 = data2;
    }
    ...

}

现在下面的代码我希望查看 JSON 数据,然后获取对象的“用户”数组列表,然后我现在想简单地将每个用户的名称打印到 LogCat 以查看它是否有效并且如前所述,我希望使用 "" 方法,因为数据非常大,我想避免内存问题。

HttpRequest request = HttpRequest.get("http://www.site.com/android/app/getAllUsers.php");   
final Reader reader = request.reader();
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
final JsonFactory factory = mapper.getFactory();

try {

    JsonParser jp = factory.createParser(reader);

    while(jp.nextToken() == JsonToken.START_OBJECT) {

        String fieldName = jp.getCurrentName();

        jp.nextToken();

        final User a = mapper.readValue(jp.getText(), User.class);

    }
} catch (JsonParseException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
} catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

但是,上面的代码在当前状态下不起作用,我从 Jackson 收到以下错误:

09-06 11:11:25.326: W/System.err(15029): com.fasterxml.jackson.databind.JsonMappingException: Current token not START_OBJECT (needed to unwrap root name 'users'), but FIELD_NAME
09-06 11:11:25.326: W/System.err(15029):  at [Source: java.io.InputStreamReader@432b1580; line: 1, column: 2]
09-06 11:11:25.326: W/System.err(15029):    at com.fasterxml.jackson.databind.ObjectMapper._unwrapAndDeserialize(ObjectMapper.java:2948)
09-06 11:11:25.326: W/System.err(15029):    at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:2858)
09-06 11:11:25.326: W/System.err(15029):    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1569)
09-06 11:11:25.326: W/System.err(15029):    at com.app.tool.UsersListActivity$LoadAllUsers.doInBackground(UsersListActivity.java:381)
09-06 11:11:25.326: W/System.err(15029):    at com.app.tool.UsersListActivity$LoadAllUsers.doInBackground(UsersListActivity.java:1)
09-06 11:11:25.326: W/System.err(15029):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
09-06 11:11:25.326: W/System.err(15029):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
09-06 11:11:25.326: W/System.err(15029):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
09-06 11:11:25.326: W/System.err(15029):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
09-06 11:11:25.326: W/System.err(15029):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
09-06 11:11:25.326: W/System.err(15029):    at java.lang.Thread.run(Thread.java:856)

我非常感谢在这方面可以提供的任何帮助,因为我被卡住了,无法继续前进。

提前致谢


******编辑** ******


感谢您的回复,我已经尝试实现代码但它似乎仍然不起作用,我现在的代码如下:

protected String doInBackground(String... args) {

    HttpRequest request = HttpRequest.get("http://www.site.com/android/app/getAllUsers.php");
    final Reader reader = request.reader();

    final ObjectMapper mapper = new ObjectMapper();
    final JsonFactory factory = mapper.getFactory();

    try {

            JsonParser jp = factory.createParser(reader);

            JsonNode root = mapper.readTree(jp);
            ArrayNode users = (ArrayNode) root.path("users");

            Iterator<JsonNode> iterator = users.elements();

            while (iterator.hasNext()) {
                User user = mapper.readValue(iterator.next(), User.class);

                System.out.println("User Name = " + user.data1);
            }

        } catch (JsonParseException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        return null;
}

您认为这与我在 ASYNC 任务中运行的进程或我通过 Web 服务访问我的 JSON 有关吗?我得到的错误及其显示的行如下:

错误行:

User user = mapper.readValue(iterator.next(), User.class);

错误代码:

The method readValue(JsonParser, Class<T>) in the type ObjectMapper is not applicable for the arguments (JsonNode, Class<User>)

希望您能帮我解决最后一个问题,再次感谢您的帮助。

【问题讨论】:

    标签: java json jackson deserialization pojo


    【解决方案1】:

    您不需要@JsonRootName 注释。您可以只读取树并获取用户数组。然后遍历并在每个节点上使用ObjectMapperreadValue(JsonNode node, Class&lt;T&gt; class)

    请注意,您的 json 中的大写 ID 需要对解析器的提示,因此在 getter 上使用 @JsonProperty(value="ID") 注释。

    public class JacksonJSON {
    
        public static void main(String[] args) throws Exception {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode root = mapper.readTree(JacksonJSON.class.getResourceAsStream("/users.json"));
            ArrayNode users = (ArrayNode) root.path("users");
    
            Iterator<JsonNode> iterator = users.getElements();
            while (iterator.hasNext()) {
                User user = mapper.readValue(iterator.next(), User.class);
    
                System.out.println("User id=" + user.id + " data1=" + user.data1 + " data2=" + user.data2);
            }
    
    
        }
    
    }
    
    
    class User {
    
        String id;
        String data1;
        String data2;
    
        @JsonProperty(value="ID")
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getData1() {
            return data1;
        }
    
        public void setData1(String data1) {
            this.data1 = data1;
        }
    
        public String getData2() {
            return data2;
        }
    
        public void setData2(String data2) {
            this.data2 = data2;
        }
    
    }
    

    【讨论】:

    • 我在 Iterator iterator = users.getElements();我收到以下错误: ArrayNode 类型的方法 getElements() 未定义
    • 我已经更新了我的问题,详细说明了实施您的建议,任何帮助都会很棒。谢谢
    • @user723858 - 你用的是什么版本的杰克逊?我用 1.9.9 测试过
    • 我使用的是最新版本
    • 为了完成,readValue接收一个JsonParser。如果您将 readValue(iterator.next(), User.class) 更改为 readValue(iterator.next().traverse(), User.class),则上述答案有效
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 2023-03-30
    • 2012-08-12
    • 1970-01-01
    相关资源
    最近更新 更多