2013-06-09 30 views
12

gson là một thư viện tuyệt vời - nó hoạt động tốt. Đôi khi tôi có các yêu cầu tùy chỉnh, và có thể tạo và đăng ký TypeAdapters và TypeAdaptorFactories - và nó cũng hoạt động tốt. Tuy nhiên, điều làm tôi bối rối là làm thế nào để ủy quyền trở lại tuần tự hóa json ... Hầu hết thời gian tôi cần điều này cho các bộ sưu tập, nhưng để minh họa cho điểm - giả sử tôi có một cặp, trong đó gson rõ ràng sẽ sắp xếp một cách vui vẻ, nhưng vì lý do nào đó, tôi cần serializer tùy chỉnh của riêng mình. Vâng ... nếu cặp của tôi làthêm đối tượng bằng cách sử dụng typeadapter tùy chỉnh, jsonwriter trong gson

public class Pair 
{ 
    public final Object First; 
    public final Object Second; 
    public Pair(Object first, Object second) {this.first = first; this.second = second}; 
} 

Nếu tôi đã viết một bộ chuyển đổi loại hình cho điều này - bạn sẽ muốn các ghi chức năng để trông giống như:

public void write(JsonWriter out, Pair pair) 
{ 
    out.beginObject(); 
    out.name("first"); 
    out.value(pair.first);   // can't do this 
    out.name("second"); 
    out.value(pair.second);   // or this 
    out.endObject(); 
} 

Vì vậy, bạn sẽ nhìn thấy vấn đề - Tôi có không có ý tưởng loại thứ nhất và thứ hai cũng như cách chúng được tuần tự hóa. Tôi có thể sử dụng gson.toJson để serialize đầu tiên và thứ hai - nhưng nếu tôi thêm chúng như là một chuỗi để các nhà văn, họ sẽ được thoát. Có một hàm gson.tojson có giá trị và một người viết - nhưng nó cũng có một kiểu gõ - mà tôi không có. Tôi sắp có ấn tượng với ý tôi là có một loại adapter khác từ đâu đó - nhưng khi tôi chỉ có một danh sách các vật thể ... tôi lấy nó ở đâu? thế nào để tôi nhận được bộ chuyển đổi cho đối tượng?

Tôi hơi bối rối? Chắc chắn đây là trường hợp sử dụng phổ biến nhất? Hầu hết các serializers tùy chỉnh sẽ cho một danh sách lạ của T hoặc cây T hoặc một cái gì đó, và bạn thực sự không biết những gì có trong danh sách, ngoài ra nó thừa kế từ T ... vì vậy bạn cần để có thể ủy nhiệm lại serialization theo một cách nào đó?

Dù sao - nếu ai đó có thể cho tôi biết cách viết hàm trên, tôi thực sự sẽ đánh giá cao nó!

Trả lời

22

Trong trường hợp này nó tốt hơn để sử dụng một JsonSerializer như trái ngược với một TypeAdapter, vì lý do đơn giản rằng serializers có quyền truy cập vào bối cảnh serialization của họ:

public class PairSerializer implements JsonSerializer<Pair> { 

    public PairSerializer() { 
     super(); 
    } 

    @Override 
    public JsonElement serialize(final Pair value, final Type type, 
      final JsonSerializationContext context) { 
     final JsonObject jsonObj = new JsonObject(); 
     jsonObj.add("first", context.serialize(value.getFirst())); 
     jsonObj.add("second", context.serialize(value.getSecond())); 

     return jsonObj; 
    } 
} 

Mã ví dụ trên minh họa cách ủy serialization của mục tiêu đối tượng trở lại marshaller chính. Ưu điểm chính của việc này (ngoài việc tránh các cách giải quyết phức tạp) là bạn vẫn có thể tận dụng các bộ điều hợp kiểu khác và serializers tùy chỉnh có thể đã được đăng ký trong ngữ cảnh chính. Lưu ý rằng việc đăng ký của serializers và adapter sử dụng cùng mã chính xác:

// With adapter 
final Gson gson = new GsonBuilder().registerTypeAdapter(Pair.class, 
     new PairAdapter()).create(); 

// With serializer 
final Gson gson = new GsonBuilder().registerTypeAdapter(Pair.class, 
     new PairSerializer()).create(); 

Nếu bạn thấy rằng bạn cần phải gắn bó với một bộ chuyển đổi, sau đó bạn có thể sử dụng một Gson Proxy nhúng để serialize các thuộc tính Pair cho bạn, với bất lợi khi bạn mất quyền truy cập vào đăng ký tùy chỉnh mà bạn đã thực hiện trên proxy Gson gốc:

public class PairAdapter extends TypeAdapter<Pair> { 
    final Gson embedded = new Gson(); 

    public PairAdapter() { 
     super(); 
    } 

    @Override 
    public void write(final JsonWriter out, final Pair value) 
      throws IOException { 
     out.beginObject(); 

     out.name("first"); 
     embedded.toJson(embedded.toJsonTree(value.getFirst()), out); 

     out.name("second"); 
     embedded.toJson(embedded.toJsonTree(value.getSecond()), out); 

     out.endObject(); 
    } 

    @Override 
    public Pair read(JsonReader in) throws IOException { 
     throw new UnsupportedOperationException(); 
    } 
} 
+0

cảm ơn bạn - sẽ cho phép điều đó –

3

thực sự dường như hoạt động - nhận bộ điều hợp cho đối tượng - sử dụng typeadaptorfactory để khám phá phương thức "json" trên đối tượng và lưu trữ đối tượng bộ điều hợp đó. Có vẻ phức tạp đáng kinh ngạc cho trường hợp sử dụng rõ ràng như thế nào?

ví dụ:

public static @Nullable 
TypeAdapter<ImmutableStack<?>> json(final Gson gson) 
{ 
    final TypeAdapter<Object> adaptor = gson.getAdapter(Object.class); 
    return new TypeAdapter<ImmutableStack<?>>() 
    { 
     @Override 
     public ImmutableStack<?> read(@Nullable final JsonReader in) throws IOException 
     { 
      throw ProgramError.notImplementedYet(); 
     } 
     @Override 
     public void write(final JsonWriter out, final ImmutableStack<?> value) throws IOException 
     { 
      out.beginArray(); 
      for (final Object inner : value) 
       adaptor.write(out, inner); 
      out.endArray(); 
     } 
    }; 
} 

không ai biết một cách tốt hơn để làm điều đó?

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