2012-04-20 35 views
6

Tôi đang sử dụng MappingJacksonHttpMessageConverter của Spring để chuyển đổi thông điệp JSON thành đối tượng trong bộ điều khiển của tôi.Deserialize ArrayList từ String sử dụng Jackson

<bean id="jsonConverter" 
    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> 
    <property name="prefixJson" value="false" /> 
    <property name="supportedMediaTypes" value="application/json" /> 
</bean> 

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> 
    <property name="messageConverters"> 
     <list> 
      <ref bean="jsonConverter" /> 
     </list> 
    </property> 
</bean> 

Đối với các trường được khai báo là ArrayList, nếu thông điệp json chứa một chuỗi thay vào đó, các ngoại lệ sau đây sẽ được ném:

org.springframework.http.converter.HttpMessageNotReadableException: 
Could not read JSON: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token 

Một ví dụ sẽ định nghĩa lớp dưới đây:

public class Product { 
    private String name; 
    private List<String> images; 
} 

Nơi Json đến là:

{name:"Widget", images:"image1.jpg"} 

Như bạn có thể thấy, điều này sẽ tạo ra ngoại lệ vì hình ảnh được mong đợi là một mảng.

Tôi muốn tạo trình tùy chỉnh deserializer dễ chịu hơn một chút. Nếu deserialization không thành công, hãy tạo một ArrayList của một phần tử đơn lẻ từ String. Làm thế nào tôi sẽ đi về tiêm này vào MappingJacksonHttpMessageConverter hoặc ObjectMapper?

Tôi không tìm cách sử dụng chú thích để đánh dấu từng và mọi trường ArrayList để có thể sử dụng deserialize tùy chỉnh. Tôi đang tìm cách ghi đè trình khử dịch mặc định để tạo sẵn chức năng này.

+0

chuỗi ban đầu bạn đang cố gắng để deserialize là gì? –

+0

nói rằng đó là {product: "1234"} thay vì {product: ["1234"]} – ltfishie

+0

và bạn đang cố gắng deserialize nó như thế nào? Bạn có thể đăng một số mã không? –

Trả lời

14

Kiểm tra bài viết này mô tả cách sử dụng các tính năng của đối tượng jacksonMapper để thực hiện việc này.

https://github.com/FasterXML/jackson-dataformat-xml/issues/21

Đối với tôi cách thêm dòng sau giải quyết vấn đề này

jsonMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 
+4

hoặc trong phiên bản 2 jsonMapper.configure (DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); –

+3

Chúa Kitô, tại sao điều này khó tìm thấy trực tuyến? * Đây là giải pháp tôi đang tìm kiếm - cảm ơn bạn. – Ryan

1

Theo tôi thấy JSON đến không chứa bất kỳ mảng nào. Câu hỏi đặt ra là: "hình ảnh" phải được tách ra hoặc nó chứa một hình ảnh duy nhất? Giả sử chúng được phân cách bằng dấu phẩy:

public class Product { 
    private String name; 
    private List<String> images; 

    @JsonProperty("images") 
    public String getImagesAsString() { 
     StringBuilder sb = new StringBuilder(); 
     for (String img : images) { 
      if (sb.length() > 0) sb.append(','); 
      sb.append(img); 
     } 
     return sb.toString(); 
    } 

    public void setImagesAsString(String img) { 
     this.images = Arrays.asList(img.split(",")); 
    } 

    @JsonIgnore 
    public List<String> getImages() { 
     return images; 
    } 
} 
+0

Cảm ơn bạn đã trả lời. Xin lỗi nếu tôi đã không làm cho nó rõ ràng, nhưng những gì tôi đang cố gắng làm là làm cho phân tích một chút khoan dung hơn. Tôi cũng muốn áp dụng điều này cho hành vi phân tích cú pháp mặc định, vì vậy tôi không cần sử dụng chú thích hoặc tạo phương thức setter thứ hai cho mọi trường. – ltfishie

+0

Tùy chọn khác là làm cho trường 'images' trở thành một chuỗi đơn giản (nếu nó chứa một hình ảnh đơn), hoặc thay đổi định dạng của chuỗi JSON để gửi một mảng thay vì một chuỗi. –

Các vấn đề liên quan