12

JSON を解析しようとしています (JSON の完全な例は、この Gistで確認できます)。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
    }
]

Jackson ライブラリを使用して 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;
    }
}

問題が何であるかを知っている人はいますか?ありがとう。

4

2 に答える 2

16

2つの簡単なこと:

  1. User クラスは、authorsプロパティを文字列として定義しています。ただし、JSON では配列であるため、Java オブジェクトでコレクションまたは配列タイプを使用する必要があります。何かのようなもの:

    private List<String> authors

  2. テスト クラスで JSON ファイルを繰り返し解析します。JSON には (1 つだけではなく) アイテムのリストがあるため、一度だけ解析する必要があり、スーパータイプ トークンを使用する必要があります。また、逆シリアル化するために間違った型を使用しています (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());
}
于 2013-03-06T18:18:50.797 に答える
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>>() {});
于 2013-03-06T15:19:36.900 に答える