2012-10-29 29 views
5

Tôi đang cố gắng để tạo ra một lớp học sử dụng Jackson để deserialize POJO của.Deserializing một loại chung với Jackson

Nó trông như thế này ...

public class DeserialiserImp<T> implements Deserialiser<T> { 

     protected ObjectMapper objectMapper = new ObjectMapper(); 

     @Override 
     public T get(String content, Class clazz) throws IOException { 
      return (T) objectMapper.readValue(content, clazz); 
     } 

     @Override 
     public List<T> getList(String content, Class clazz) throws IOException { 
      return objectMapper.readValue(content, TypeFactory.collectionType(ArrayList.class, clazz)); 
     } 

    } 

Tôi có 2 câu hỏi về việc thực hiện này.

Đầu tiên là tôi chuyển loại lớp vào các phương thức để đối tượng trình biết loại cần deserialize. Có cách nào tốt hơn bằng cách sử dụng generics? Cũng trong phương thức get, tôi đang truyền một đối tượng được trả về từ objectMapper đến T. Điều này có vẻ đặc biệt khó chịu khi thực hiện nó vì tôi phải cast T ở đây và sau đó tôi cũng phải cast kiểu đối tượng từ phương thức đang gọi nó.

Tôi đang sử dụng Roboguice trong dự án này vì vậy sẽ tốt hơn nếu tôi có thể thay đổi loại thông qua tiêm và sau đó chú thích đối tượng mà loại Generic tôi cần để trả lại. Tôi đọc về TypeLiteral và tự hỏi nếu nó có thể giải quyết vấn đề này?

+0

Xem http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

Trả lời

5

Vì vậy, tôi nghĩ rằng tôi đã tìm ra nó cuối cùng. Hãy bình luận nếu bạn thấy điều gì đó sai trái với những gì tôi đang làm.

Giao diện được định nghĩa như vậy ...

public interface Deserialiser<T> { 

    T get(String content) throws IOException; 

    List<T> getList(String content) throws IOException; 
} 

Việc thực hiện của giao diện là như thế này ...

public class DeserialiserImp<T> implements Deserialiser<T> { 

    private ObjectMapper objectMapper = new ObjectMapper(); 
    private final Class<T> klass; 

    @Inject 
    public DeserialiserImp(TypeLiteral<T> type){ 
     this.klass = (Class<T>) type.getRawType(); 
    } 

    @Override 
    public T get(String content) throws IOException { 
     return objectMapper.readValue(content, klass); 
    } 

    @Override 
    public List<T> getList(String content) throws IOException { 
     return objectMapper.readValue(content, TypeFactory.collectionType(ArrayList.class, klass)); 
    } 

} 

tôi ràng buộc 2 như vậy ..

bind(new TypeLiteral<Deserialiser<User>>(){}).annotatedWith(Names.named("user")).to(new TypeLiteral<DeserialiserImp<User>>(){}); 

Sau đó, tất cả những gì cần phải làm gì để sử dụng nó là thế này ...

@Inject 
@Named("user") 
private Deserialiser<User> deserialiserImp; 

public void test(String userString) { 
    User user = deserialiserImp.get(UserString); 
} 

mô hình này cũng có thể hoạt động tốt nếu lớp như một lớp trừu tượng để sử dụng trong một đối tượng DAO

This bài viết đã giúp tôi

5

Đầu tiên là tôi chuyển loại lớp vào các phương thức để đối tượng biết loại cần deserialize. Có cách nào tốt hơn bằng cách sử dụng generics?

Thật không may là không, và điều này là do loại xóa.

Cũng trong method get tôi đúc một đối tượng trở về từ các objectMapper để T. Điều này có vẻ cách tranh bóng ác ý làm việc đó như tôi phải đúc T ở đây và sau đó tôi phải cũng đúc các loại đối tượng từ phương thức đang gọi nó.

Làm điều này thay vì:

@Override 
public T get(String content, Class<T> clazz) throws IOException { 
    return objectMapper.readValue(content, clazz); 
} 

Tôi đang sử dụng Roboguice trong dự án này, do đó nó sẽ được tốt đẹp nếu tôi có thể thay đổi kiểu qua tiêm chích và sau đó chú thích các đối tượng mà kiểu Generic Tôi cần nó để trở về. Tôi đọc về TypeLiteral và tự hỏi nếu nó có thể giải quyết vấn đề này?

Tôi không thực sự hiểu những gì bạn muốn đạt được, nhưng vì bạn cần phải vượt qua lớp dù sao, liệu vẫn có thể?

+0

Điểm của tôi về việc sử dụng TypeLiteral s từ câu hỏi này http://stackoverflow.com/questions/3370641/how-does-guices-typeliteral-work Nó nói rằng "Bí quyết được sử dụng ở đây là chữ ký của các loại siêu chung được lưu trữ trong các lớp con và do đó tồn tại tẩy xoá. " Tôi hy vọng không vượt qua trong loại. – jiduvah

+1

Ok tôi hiểu. Tôi không thấy bất kỳ giải pháp thực tế ở đây, bạn cần phải lưu trữ các loại ở đâu đó (đối tượng Class đồng bằng như trường, sử dụng TypeLiteral vv ...) để lấy nó khi chạy. Tôi không nghĩ rằng việc vượt qua loại mỗi lần là một vấn đề lớn, vì nó là yêu cầu của tất cả các thư viện unmarshalling. Tôi sẽ được quan tâm để xem một cách tiếp cận khác mặc dù. –

+0

Vâng, tôi đang cố gắng làm cho mã sạch hơn. Tại thời điểm tôi vượt qua trong các loại như là một chung chung khi instantiating deserialiserImp, tôi phải vượt qua trong lớp vào phương pháp, sau đó tôi cũng cần phải cast các đối tượng mà tôi nhận được. Vì vậy, thats 3 lần tôi tham khảo các loại. Nó có vẻ rất messey – jiduvah

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