使用Jackson Mapper将JSON数据映射到Java POJO类

5

我正在开发一个安卓应用程序,并尝试使用Jackson的流功能来处理一些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代码,其中数据将在迭代数据中的每个“users”数组列表项时存储:

@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数据,然后获取“users”对象数组列表,现在我只想先将每个用户的姓名打印到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;
}

您觉得这是否与我的进程在异步任务中运行或通过 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>)

希望你能帮我解决这个最后的问题,再次感谢你的帮助。
1个回答

1
你不需要使用 @JsonRootName 注解。你可以直接读取树形结构并获取用户数组,然后遍历每个节点并在每个节点上使用 ObjectMapperreadValue(JsonNode node, Class<T> 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<JsonNode> iterator = users.getElements(); 这行代码中得到了以下错误:方法 getElements() 未被 ArrayNode 类型定义。 - user723858
我已经更新了我的问题,附上实现您建议的细节,任何帮助将不胜感激。谢谢。 - user723858
我正在使用最新版本。 - user723858
你是在建议我使用旧版本吗? - user723858
1
为了完整起见,readValue接收一个JsonParser。如果您将readValue(iterator.next(), User.class)更改为readValue(iterator.next().traverse(), User.class),上面的答案就可以工作。 - JACH
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接