Nhiều GSON @SerializedName trên mỗi trường?


104

Có cách nào trong Gson để ánh xạ nhiều trường JSON đến một biến thành viên đối tượng Java duy nhất không?

Giả sử tôi có một lớp Java ...

public class MyClass {
    String id;
    String name;
}

Tôi muốn sử dụng lớp đơn này với hai dịch vụ khác nhau. Tuy nhiên, hai dịch vụ này khác nhau về cách chúng trả lại dữ liệu của chúng ...

{ "id": 2341, "person": "Bob" }

... và ...

{ "id": 5382, "user": "Mary" }

... tương ứng.

Có cách nào để ánh xạ cả trường "person""user"trường trong chuỗi JSON với nametrường trong đối tượng Java không?

(Lưu ý: Tôi chỉ cần chuyển đổi từ chuỗi JSON sang đối tượng Java - không bao giờ ngược lại.)


1
Đây là đơn giản và hoàn hảo giải thích futurestud.io/tutorials/...
Atul Bhardwaj

Câu trả lời:


238

Vào tháng 10 năm 2015, Gson phiên bản 2.4 ( changelog ) đã thêm khả năng sử dụng thay thế / nhiều tên cho @SerializedNamekhi giải bóng. Không cần TypeAdapter tùy chỉnh nữa!

Sử dụng:

@SerializedName(value="name", alternate={"person", "user"})

https://www.javadoc.io/doc/com.google.code.gson/gson/2.6.2/com/google/gson/annotations/SerializedName.html


1
Đây là đơn giản và hoàn hảo giải thích futurestud.io/tutorials/...
Atul Bhardwaj

Kinh ngạc! Cảm ơn bạn vì câu trả lời này!
sunlover3

câu trả lời tuyệt vời, cảm ơn!
Dor Rud

27

Nó không được hỗ trợ để xác định nhiều @SerializedNamechú thích cho một trường tại Gson.

Lý do: Theo mặc định, Deserialization được quản lý bằng một LinkedHashMap và các khóa được xác định bởi tên trường của json đến (không phải tên trường của lớp tùy chỉnh hoặc serializedNames) và có một ánh xạ 1-1. Bạn có thể thấy việc triển khai (cách deserialization hoạt động) tại phương thức của ReflectiveTypeAdapterFactorylớp bên trong của lớp .Adapter<T>read(JsonReader in)

Giải pháp: Bạn có thể viết một tùy chỉnh TypeAdapter mà xử lý name, personuserthẻ json và bản đồ chúng đến lĩnh vực tên của lớp tùy chỉnh của bạn MyClass:

class MyClassTypeAdapter extends TypeAdapter<MyClass> {

    @Override
    public MyClass read(final JsonReader in) throws IOException {
        final MyClass myClassInstance = new MyClass();

        in.beginObject();
        while (in.hasNext()) {
            String jsonTag = in.nextName();
            if ("id".equals(jsonTag)) {
                myClassInstance.id = in.nextInt();
            } else if ("name".equals(jsonTag) 
                    || "person".equals(jsonTag)
                    || "user".equals(jsonTag)) {
                myClassInstance.name = in.nextString();
            }
        }
        in.endObject();

        return myClassInstance;
    }

    @Override
    public void write(final JsonWriter out, final MyClass myClassInstance)
            throws IOException {
        out.beginObject();
        out.name("id").value(myClassInstance.id);
        out.name("name").value(myClassInstance.name);
        out.endObject();
    }
}

Trường hợp thử nghiệm:

    String jsonVal0 = "{\"id\": 5382, \"user\": \"Mary\" }";
    String jsonVal1 = "{\"id\": 2341, \"person\": \"Bob\"}";

    final GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(MyClass.class, new MyClassTypeAdapter());
    final Gson gson = gsonBuilder.create();

    MyClass myClassInstance0 = gson.fromJson(jsonVal0, MyClass.class);
    MyClass myClassInstance1 = gson.fromJson(jsonVal1, MyClass.class);

    System.out.println("jsonVal0 :" + gson.toJson(myClassInstance0));
    // output: jsonVal0 :{"id":5382,"name":"Mary"}

    System.out.println("jsonVal1 :" + gson.toJson(myClassInstance1));
    // output: jsonVal1 :{"id":2341,"name":"Bob"}

Ví dụ về TypeAdapters.

Chỉnh sửa 2016.04.06: Như @Mathieu Castets đã viết trong câu trả lời của mình, nó hiện được hỗ trợ. (Đó là câu trả lời chính xác cho câu hỏi này.)

public abstract String [] alternate
Trả về: tên thay thế của trường khi nó được deserialized
Mặc định: {}


Đây là đơn giản và hoàn hảo giải thích futurestud.io/tutorials/...
Atul Bhardwaj

20

dành cho người hâm mộ Kotlin

@SerializedName(value="name", alternate= ["person", "user"])

8

Đối với KOTLIN, tôi đã sử dụng bên dưới nhưng không hoạt động

@SerializedName(value="name", alternate= ["person", "user"])

vì vậy tôi đã chỉnh sửa nó và ở đây nó hoạt động tốt !!

@SerializedName(value="name", alternate= arrayOf("person", "user"))
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.