JsonMappingException: hết mã thông báo START_ARRAY


112

Cho tệp .json sau:

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

Tôi đã chuẩn bị hai lớp để đại diện cho dữ liệu được chứa:

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

...

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

Để phân tích cú pháp nội dung từ tệp .json, tôi sử dụng Jackson 2.2.x và chuẩn bị phương pháp sau:

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;
}

Miễn là tôi bỏ qua thuộc centertính, tất cả nội dung có thể được phân tích cú pháp. Tuy nhiên, khi tôi cố gắng phân tích cú pháp tọa độ địa lý, tôi nhận được thông báo lỗi sau:

com.fasterxml.jackson.databind.JsonMappingException: Không thể giải mã hóa phiên bản
com.example.GeoPoint ra khỏi mã thông báo START_ARRAY tại [Nguồn: android.content.res.AssetManager$AssetInputStream@416a5850; dòng: 5, cột: 25]
(thông qua chuỗi tham chiếu: com.example.Location ["center"])


lý do tại sao bạn đang sử dụng jackson nếu bạn chỉ có thể phân tích nó với phân tích cú pháp JSON
Shashank Agarwal

4
Chuỗi JSON của bạn không đúng định dạng, kiểu centerlà một mảng các đối tượng không hợp lệ. Cố gắng thay thế []bằng {}trong chuỗi JSON xung quanh longitudelatitudevì vậy chúng sẽ là các đối tượng.
Katona

1
@Katona Cảm ơn bạn. Bạn có thể vui lòng chuyển bình luận của bạn thành một câu trả lời để tôi có thể đóng câu hỏi được không ?!
JJD

Câu trả lời:


75

Chuỗi JSON của bạn không đúng định dạng: kiểu centerlà một mảng các đối tượng không hợp lệ. Thay thế []bằng {}trong chuỗi JSON xung quanh longitudelatitudevì vậy chúng sẽ là các đối tượng:

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

1
Tôi cũng gặp phải vấn đề tương tự, nhưng thật điên rồ vì trong jackson 2.6.3v có một lỗi hoàn toàn khác và với 2.9.8v mọi thứ đều hoạt động. Khỉ thật, những lỗi tuần tự hóa này thật khó chịu.
brebDev

114

JsonMappingException: out of START_ARRAY tokenngoại lệ được trình lập bản đồ đối tượng Jackson ném ra vì nó mong đợi một phản hồi Object {}trong khi nó tìm thấy một Array [{}]phản hồi.

Điều này có thể được giải quyết bằng cách thay thế Objectbằng Object[]trong đối số cho geForObject("url",Object[].class). Người giới thiệu:

  1. Tham khảo 1
  2. Tham khảo 2
  3. Tham khảo 3

9

Tôi đã sắp xếp vấn đề này như xác minh json từ JSONLint.com và sau đó, sửa nó. Và đây là mã cho cùng một.

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");
}

Lưu ý: MyPojo[].classlà lớp có getter và setter của thuộc tính json.

Kết quả:

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

1
Điều này đã khắc phục sự cố mà tôi đã gặp phải trong nhiều ngày, không có câu trả lời nào khác hợp lý. Đối với bất kỳ ai khác có cùng một lỗi. Cần lưu ý rằng nếu JSON của bạn có nhiều đối tượng, bạn cần phải trả về nhiều đối tượng. Tôi đã trả lại MyObject, nơi đáng lẽ tôi phải trả lại MyObject []
Aaria

8

Như đã nói, người JsonMappingException: out of START_ARRAY tokenlập bản đồ đối tượng Jackson ném ra ngoại lệ vì nó đang mong đợi một phản hồi Object {}trong khi nó tìm thấy một Array [{}]phản hồi.

Một giải pháp đơn giản hơn có thể thay thế phương pháp này getLocationsbằng:

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;
}

Mặt khác, nếu bạn không có giống pojo Location, bạn có thể sử dụng:

TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<>() {};
return objectMapper.readValue(inputStream, typeReference);

1
Cảm ơn bạn đã chia sẻ triển khai thay thế này. Bạn có thể cho biết nếu có những ưu điểm hay nhược điểm với việc sử dụng CollectionTypevs TypeReference?
JJD

1
TypeReferencecú pháp ngắn hơn nhiều so với cú pháp khác. Không chắc, nếu trong một số trường hợp có thể có một chỉ dẫn ngược lại liên quan đến việc tẩy xóa kiểu ... nhưng trong thế giới của tôi TypeReferencethì dễ sử dụng và dễ hiểu hơn.
freedev
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.