2013-01-14 16 views
10

Tôi có dịch vụ Web REST dựa trên json được triển khai thực hiện bằng cách sử dụng: Jetty, Jersey, Jersey-JSON sử dụng Jackson.Jersey: Không thể deserialize trường hợp của ArrayList ra khỏi chuỗi

Một trong các phương pháp của tôi nhận được cá thể Cá nhân có trường loại Danh sách < Chuỗi >. tức là:

Public class Person { 
    List<String> names; 
} 

Nếu tôi gọi nó với một loạt tên, tất cả đều hoạt động ok! ví dụ:

{ "names" : [ "Jhon", "Doe" ] } 

Nhưng nếu người đó chỉ có một tên, khách hàng của tôi tạo ra một yếu tố giá trị duy nhất, ví dụ:

{ "names" : "Jhon" } 

Khi tôi cố gắng gọi cho dịch vụ với một giá trị duy nhất, tôi nhận được một ngoại lệ:

Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token 

Câu hỏi:

Làm thế nào tôi nên tạo/cấu hình dịch vụ web của tôi, để có thể deserialize mảng trường khi chúng được gửi đến tôi như là một phần tử duy nhất.

-

Tôi đã đọc:

Jackson deserialization - with contained ArrayList<T>

How can I customize serialization of a list of JAXB objects to JSON?

và điều này mà tham khảo câu trả lời cuối cùng:

Jersey client can not deserializable json services - exception(can not deserialize instance)

Jaxb json missing brackets for one element array

Nhưng không ai trong số đó khắc phục được sự cố.

Cảm ơn bạn trước!

Trả lời

11

Sau một ngày dài, và một ... sau khi đọc rất nhiều wiki và faqs, nó cuối cùng hoạt động.

Những gì tôi đã làm:

  1. Sử dụng Jackson
  2. Force Jackson các nhà cung cấp sử dụng
  3. Xác định tùy chỉnh deserializer
  4. kích hoạt ACCEPT_SINGLE_VALUE_AS_ARRAY cờ
  5. Fix phụ thuộc

Câu chuyện:

Tôi đã sử dụng Jersey 1.13 sử dụng (tôi tin) jaxb theo mặc định.

tôi đã thay đổi nó để sử dụng Jackson

<init-param> 
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> 
    <param-value>true</param-value> 
</init-param> 

như mô tả tại địa chỉ:

https://stackoverflow.com/a/13895768/660990

Điều này làm áo của tôi sử dụng jackson, nhưng vấn đề vẫn còn; jackson không thể deserializer mảng nào được nêu ra.

tôi buộc việc sử dụng các nhà cung cấp Jackson:

<init-param> 
    <param-name>com.sun.jersey.config.property.packages</param-name> 
    <param-value> 
     your.project.packages; 
     org.codehaus.jackson.jaxrs</param-value> 
</init-param> 

https://stackoverflow.com/a/3143214/660990

là một bước cần thiết, nhưng chưa đủ. Cần phải kích hoạt cờ ACCEPT_SINGLE_VALUE_AS_ARRAY.

ObjectMapper objectMapper; 
objectMapper = new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 

tôi cần xác định tùy chỉnh deserializer

public class MyResolver implements ContextResolver<ObjectMapper> { 

@Override 
    public ObjectMapper getContext(final Class<?> objectType) { 
     ...    
     return objectMapper; 
    } 
} 

để làm điều đó:

Customizing-ObjectMapper

Sau khi thực hiện tất cả những điều đó vẫn không làm việc ...

Sau một thời gian tìm kiếm, tôi thấy:

Jackson 2.0 with Jersey 1.12

Đó thảo luận phụ thuộc vấn đề ..

này reveled vấn đề của tôi, Jersey v1.13 tàu với Jackson v1.9.2 tôi cần Jackson v2.0

Tôi đã xóa phụ thuộc cho jersey-json, vì nó bao gồm jackson 1.9.2:

<dependency> 
    <groupId>com.sun.jersey</groupId> 
    <artifactId>jersey-json</artifactId> 
</dependency> 

Và tuyên bố trực tiếp phụ thuộc cho:

<dependency> 
    <groupId>com.fasterxml.jackson.jaxrs</groupId> 
    <artifactId>jackson-jaxrs-json-provider</artifactId> 
</dependency> 

tham khảo:

jackson-jaxrs-json-provider

Lưu ý: thay đổi này loại bỏ khả năng Jersey sử dụng JAXB hoặc vứt bỏ.

Tắt chủ đề, có thể là thú vị cho ai đó:

Configure Jersey/Jackson to NOT use @XmlElement field annotation for JSON field naming

+0

Cảm ơn bạn đời, dòng sau đã giải quyết được vấn đề của tôi: objectMapper = new ObjectMapper(). Configure (DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); – mojsilo

+0

@mojsilo bạn đang đặt ** objectMapper = new ObjectMapper(). Configure (DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); ** ? – Luke

+0

Tôi đã đặt nó vào hàm tạo của dịch vụ mapper.configure (\t \t org.codehaus.jackson.map.DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); – mojsilo

1

Ví dụ 5.10 và 5.11 trong số this page giải thích vấn đề chính xác của bạn. Bạn có thể định cấu hình trình tạo JSON để buộc mảng cho danh sách một mục, như vậy: JSONConfiguration.mapped().arrays("names").build().

+1

Cảm ơn bạn! Nhưng tôi muốn sửa lỗi này ở phía máy chủ. Đã cập nhật câu hỏi của tôi để rõ ràng. –

+0

Bạn sẽ thêm ** JSONConfiguration.mapped(). Mảng ("tên"). Build() ** vào ứng dụng khách? Khi bạn đã xây dựng yêu cầu, nhưng trước khi gửi nó? – Luke

1

Nó làm việc cho tôi bằng cách thêm @JsonSerialize đến lớp

@JsonSerialize 
Public class Person { 
    List<String> names; 
} 
0
{"results": {"place": {"lang": "en-US","woeid": "2168606"}}} 

&

{"results": {"place": [{"lang": "en-US","woeid": "2168606"}, {"lang": "en-US","woeid": "2168606"}]}} 

kiểu này làm thế nào để làm ... khi sử dụng yahoo nơi api

1

Bạn có thể làm điều này với chú thích ở lớp, lĩnh vực hoặc cấp phương pháp sử dụng các chú thích JsonFormat

@JsonFormat(with = Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) 
protected List<String> list; 

public List<String> getList() { 
    return list; 
} 

public void setList(List<String> list) { 
    this.list = list; 
}