2013-03-06 87 views
11

我想解析一些JSON(JSON的完整示例可以在this Gist中看到)。我在下面的JSON的一般结构:错误使用杰克逊和Json

[ 
    { 
     "title": "Principles of Compiler Design", 
     "authors": [ 
      "Aho", 
      "Ullman" 
     ], 
     "publisher": "Addison Wesley", 
     "year": 1977 
    }, 
    { 
     "title": "Compilers: Principles Techniques and Tools", 
     "authors": [ 
      "Aho", 
      "Sethi", 
      "Ullman" 
     ], 
     "publisher": "Addison Wesley", 
     "year": 1985 
    } 
] 

我想与杰克逊库解析JSON,但我得到了下面的错误,而测试:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token 
at [Source: library.json; line: 2, column: 49] (through reference chain: com.acme.datatypes.User["authors"]) 
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:163) 
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:588) 
    at com.fasterxml.jackson.databind.deser.std.JdkDeserializers$StringDeserializer.deserialize(JdkDeserializers.java:90) 
    at com.fasterxml.jackson.databind.deser.std.JdkDeserializers$StringDeserializer.deserialize(JdkDeserializers.java:59) 
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:336) 
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:89) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:290) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:112) 
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2563) 
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1759) 
    at com.acme.datatypes.UserTest.main(UserTest.java:20) 

这里是我的代码:

用户测试类:

public class UserTest { 
    public static void main(String[] args) throws JsonParseException, 
      JsonMappingException, IOException { 
     File jsonFile = new File("library.json"); 

     User user = null; 

     ObjectMapper mapper = new ObjectMapper(); 

     user = mapper.readValue(jsonFile, User.class); 
     System.out.println(user.getTitle()); 

     user = mapper.readValue(jsonFile, User.class); 
     System.out.println(user.getAuthors()); 

     user = mapper.readValue(jsonFile, User.class); 
     System.out.println(user.getPublisher()); 

     user = mapper.readValue(jsonFile, User.class); 
     System.out.println(user.getYear()); 
    } 
} 

用户等级:

public class User { 

    private String authors; 
    private String publisher; 
    private String title; 
    private Number year; 

    public String getAuthors() { 
     return this.authors; 
    } 

    public void setAuthors(String authors) { 
     this.authors = authors; 
    } 

    public String getPublisher() { 
     return this.publisher; 
    } 

    public void setPublisher(String publisher) { 
     this.publisher = publisher; 
    } 

    public String getTitle() { 
     return this.title; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 

    public Number getYear() { 
     return this.year; 
    } 

    public void setYear(Number year) { 
     this.year = year; 
    } 
} 

有谁知道这个问题可能是什么?谢谢。

+0

可以共享java代码也,你需要将其转换为一个列表 – 2013-03-06 15:17:43

+0

你怎么宣布你'authors'财产?它应该是一个集合或数组类型。 – Perception 2013-03-06 15:25:05

+0

@Arun P Johny,我编辑了文档并添加了代码,以供您参阅 – tribrick 2013-03-06 17:59:20

回答

15

两个快速件事:

  1. 您的用户类定义authors属性为一个字符串。但是在JSON中它是一个数组,因此您需要在Java对象中使用集合或数组类型。喜欢的东西:

    private List<String> authors

  2. 您反复分析你的测试类的JSON文件。你只需要解析一次,并且你需要使用一个超类型标记,因为JSON中有一个项目列表(不只是一个)。您也正在使用错误的类型来反序列化(User.class)。不过,所有这些行:

    user = mapper.readValue(jsonFile, User.class); System.out.println(user.getTitle());

    user = mapper.readValue(jsonFile, User.class); // <-- unnecessary parsing System.out.println(user.getAuthors());

    user = mapper.readValue(jsonFile, User.class); // <-- unnecessary parsing System.out.println(user.getPublisher());

    user = mapper.readValue(jsonFile, User.class); // <-- unnecessary parsing System.out.println(user.getYear());

只需使用:

List<User> userList = 
    mapper.readValue(jsonFile, new TypeReference<List<User>>() {}); 

一旦您获得测试类中的用户列表,您可以使用增强for循环对它们进行迭代。

for(User user : userList) { 
    System.out.println(user.getTitle()); 
} 
+1

它很明显,但即时得到这个错误现在:线程“主”的异常com.fasterxml.jackson.core.JsonParseException:在ARRAY条目之内/之间意外的输入结束 at [Source :library.json; line:11,column:200] – tribrick 2013-03-06 18:29:27

+0

@tribrick - 将你的JSON文件的内容转储到[jsonlint](http://jsonlint.com)中,并验证它是格式良好的。 – Perception 2013-03-06 18:30:51

+0

是的,这是一个有效的JSON文件 – tribrick 2013-03-06 18:35:35

4

由于您使用数组,你需要将其转换成一个数组或列表

由于阵列

MyClass[] myObjects = mapper.readValue(json, MyClass[].class); 

方式列表

List<MyClass> myObjects = mapper.readValue(jsonInput, new TypeReference<List<MyClass>>(){}); 

用户

public class User { 

    private List<String> authors; 
    private String publisher; 
    private String title; 
    private Number year; 

    public List<String> getAuthors() { 
     return this.authors; 
    } 

    public void setAuthors(List<String> authors) { 
     this.authors = authors; 
    } 

    public String getPublisher() { 
     return this.publisher; 
    } 

    public void setPublisher(String publisher) { 
     this.publisher = publisher; 
    } 

    public String getTitle() { 
     return this.title; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 

    public Number getYear() { 
     return this.year; 
    } 

    public void setYear(Number year) { 
     this.year = year; 
    } 
} 

用法:

List<User> l = mapper.readValue(new File(""),new TypeReference<List<User>>() {});