JsonMappingException: dari token START_ARRAY

112

Diberikan file .json berikut:

[
    {
        "name" : "New York",
        "number" : "732921",
        "center" : [
                "latitude" : 38.895111, 
                "longitude" : -77.036667
            ]
    },
    {
        "name" : "San Francisco",
        "number" : "298732",
        "center" : [
                "latitude" : 37.783333, 
                "longitude" : -122.416667
            ]
    }
]

Saya menyiapkan dua kelas untuk mewakili data yang terkandung:

public class Location {
    public String name;
    public int number;
    public GeoPoint center;
}

...

public class GeoPoint {
    public double latitude;
    public double longitude;
}

Untuk mengurai konten dari file .json saya menggunakan Jackson 2.2.x dan menyiapkan metode berikut:

public static List<Location> getLocations(InputStream inputStream) {
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        TypeFactory typeFactory = objectMapper.getTypeFactory();
        CollectionType collectionType = typeFactory.constructCollectionType(
                                            List.class, Location.class);
        return objectMapper.readValue(inputStream, collectionType);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Selama saya meninggalkan centerproperti, semua konten dapat diurai. Namun, ketika saya mencoba mengurai geo-koordinat saya berakhir dengan pesan kesalahan berikut:

com.fasterxml.jackson.databind.JsonMappingException: Tidak dapat menghapus nama instance
com.example.GeoPoint dari token START_ARRAY di [Sumber: android.content.res.AssetManager$AssetInputStream@416a5850; baris: 5, kolom: 25]
(melalui rantai referensi: com.example.Location ["center"])

JJD
sumber
mengapa Anda menggunakan jackson jika Anda dapat menguraikannya dengan json parser
Shashank Agarwal
4
String JSON Anda salah format, jenisnya centeradalah larik objek yang tidak valid. Coba ganti [dan ]dengan {dan }dalam string JSON sekitar longitudedan latitudesehingga mereka akan benda-benda.
Katona
1
@KatTerima kasih. Bisakah Anda mengubah komentar Anda menjadi jawaban sehingga saya bisa menutup pertanyaan ?!
JJD

Jawaban:

75

String JSON Anda salah format: jenisnya centeradalah larik objek yang tidak valid. Ganti [dan ]dengan {dan }dalam string JSON sekitar longitudedan latitudesehingga mereka akan menjadi objek:

[
    {
        "name" : "New York",
        "number" : "732921",
        "center" : {
                "latitude" : 38.895111, 
                "longitude" : -77.036667
            }
    },
    {
        "name" : "San Francisco",
        "number" : "298732",
        "center" : {
                "latitude" : 37.783333, 
                "longitude" : -122.416667
            }
    }
]
Katona
sumber
1
Masalah yang sama saya miliki, tetapi ini gila karena di jackson 2.6.3v ada kesalahan gila yang sama sekali berbeda, dan dengan 2.9.8v semuanya bekerja. Sial, jadi kesalahan serialisasi ini sangat mengganggu.
brebDev
114

JsonMappingException: out of START_ARRAY tokenpengecualian dilemparkan oleh mapper objek Jackson karena ia mengharapkan Object {}sedangkan ia menemukan sebagai Array [{}]tanggapan.

Ini dapat diselesaikan dengan mengganti Objectdengan Object[]dalam argumen untuk geForObject("url",Object[].class). Referensi:

  1. Ref.1
  2. Ref.2
  3. Ref.3
Abhijeet
sumber
9

Saya mengurutkan masalah ini sebagai memverifikasi json dari JSONLint.com dan kemudian, memperbaikinya. Dan ini adalah kode yang sama.

String jsonStr = "[{\r\n" + "\"name\":\"New York\",\r\n" + "\"number\": \"732921\",\r\n"+ "\"center\": {\r\n" + "\"latitude\": 38.895111,\r\n"  + " \"longitude\": -77.036667\r\n" + "}\r\n" + "},\r\n" + " {\r\n"+ "\"name\": \"San Francisco\",\r\n" +\"number\":\"298732\",\r\n"+ "\"center\": {\r\n" + "    \"latitude\": 37.783333,\r\n"+ "\"longitude\": -122.416667\r\n" + "}\r\n" + "}\r\n" + "]";

ObjectMapper mapper = new ObjectMapper();
MyPojo[] jsonObj = mapper.readValue(jsonStr, MyPojo[].class);

for (MyPojo itr : jsonObj) {
    System.out.println("Val of name is: " + itr.getName());
    System.out.println("Val of number is: " + itr.getNumber());
    System.out.println("Val of latitude is: " + 
        itr.getCenter().getLatitude());
    System.out.println("Val of longitude is: " + 
        itr.getCenter().getLongitude() + "\n");
}

Catatan: MyPojo[].classadalah kelas yang memiliki properti getter dan setter json.

Hasil:

Val of name is: New York
Val of number is: 732921
Val of latitude is: 38.895111
Val of longitude is: -77.036667
Val of name is: San Francisco
Val of number is: 298732
Val of latitude is: 37.783333
Val of longitude is: -122.416667
Atul Sharma
sumber
1
Ini memperbaiki masalah yang saya alami selama berhari-hari, tidak ada jawaban lain yang masuk akal. Untuk orang lain yang mengalami kesalahan yang sama. Perlu dicatat bahwa jika JSON Anda memiliki banyak objek, Anda perlu mengembalikan beberapa objek. Saya telah mengembalikan MyObject, di mana saya seharusnya mengembalikan MyObject []
Aaria
8

Seperti yang dikatakan, JsonMappingException: out of START_ARRAY tokenpengecualian dilemparkan oleh pemeta objek Jackson karena mengharapkan Object {}sementara itu menemukan Array [{}]tanggapan.

Solusi yang lebih sederhana dapat mengganti metode getLocationsdengan:

public static List<Location> getLocations(InputStream inputStream) {
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        TypeReference<List<Location>> typeReference = new TypeReference<>() {};
        return objectMapper.readValue(inputStream, typeReference);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Di sisi lain, jika Anda tidak menyukai pojo Location, Anda dapat menggunakan:

TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<>() {};
return objectMapper.readValue(inputStream, typeReference);
freedev
sumber
1
Terima kasih telah membagikan implementasi alternatif ini. Dapatkah Anda mengetahui apakah ada keuntungan atau kerugian menggunakan CollectionTypevs. TypeReference?
JJD
1
TypeReferencesintaks jauh lebih pendek dari yang lain. Tidak yakin, jika dalam beberapa kasus mungkin ada indikasi balasan terkait dengan jenis penghapusan ... tetapi di dunia saya TypeReferencelebih mudah digunakan dan dipahami.
freedev