Gson: Cách loại trừ các trường cụ thể khỏi Tuần tự hóa mà không cần chú thích


388
134
Phan Liên Hoa
9 năm trước

Tôi đang cố gắng học Gson và tôi đang vật lộn với loại trừ trường. Đây là lớp học của tôi

public class Student {    
  private Long                id;
  private String              firstName        = "Philip";
  private String              middleName       = "J.";
  private String              initials         = "P.F";
  private String              lastName         = "Fry";
  private Country             country;
  private Country             countryOfBirth;
}

public class Country {    
  private Long                id;
  private String              name;
  private Object              other;
}

Tôi có thể sử dụng GsonBuilder và thêm ExinatingStrargety cho một tên trường như firstNamehoặc countrynhưng dường như tôi không thể quản lý để loại trừ các thuộc tính của các trường nhất định như country.name.

Sử dụng phương thức public boolean shouldSkipField(FieldAttributes fa), FieldAttribution không chứa đủ thông tin để khớp trường với bộ lọc như thế nào country.name.

Tôi sẽ đánh giá cao bất kỳ trợ giúp với một giải pháp cho vấn đề này.

PS: Tôi muốn tránh các chú thích vì tôi muốn cải thiện điều này và sử dụng RegEx để lọc các trường.

Cảm ơn bạn

Chỉnh sửa : Tôi đang cố gắng xem liệu có thể mô phỏng hành vi của plugin Struts2 JSON không

sử dụng Gson

<interceptor-ref name="json">
  <param name="enableSMD">true</param>
  <param name="excludeProperties">
    login.password,
    studentList.*\.sin
  </param>
</interceptor-ref>

Chỉnh sửa: Tôi mở lại câu hỏi với phần bổ sung sau:

Tôi đã thêm một trường thứ hai với cùng loại để làm rõ hơn vấn đề này. Về cơ bản tôi muốn loại trừ country.namenhưng không countrOfBirth.name. Tôi cũng không muốn loại trừ Quốc gia thành một loại. Vì vậy, các loại giống nhau, đó là vị trí thực tế trong biểu đồ đối tượng mà tôi muốn xác định và loại trừ.

Hữu ích 388 Yêu thích 134 Chia sẻ Viết bình luận 3
Không hữu ích

Vẫn là phiên bản 2.2 Tôi vẫn không thể chỉ định đường dẫn đến trường để loại trừ. flexjson.sourceforge.net cảm thấy như một sự thay thế tốt.

Hữu ích 0 · Không hữu ích · Trả lời 0

Hãy xem câu trả lời của tôi cho một câu hỏi tương tự. Nó dựa trên việc tạo một tùy chỉnh JsonSerializercho một số loại - Countrytrong trường hợp của bạn - sau đó được áp dụng một trường ExclusionStrategyquyết định những trường nào sẽ tuần tự hóa.

Hữu ích 0 · Không hữu ích · Trả lời 0
Hữu ích 0 · Không hữu ích · Trả lời 0

15 Trả lời


592
Đặng Thái Minh
9 năm trước

Bất kỳ trường nào bạn không muốn tuần tự hóa nói chung, bạn nên sử dụng công cụ sửa đổi "tạm thời" và điều này cũng áp dụng cho trình xê-ri json (ít nhất là đối với một số mà tôi đã sử dụng, bao gồm cả gson).

Nếu bạn không muốn tên hiển thị trong json nối tiếp, hãy đặt cho nó một từ khóa thoáng qua, ví dụ:

private transient String name;

Thêm chi tiết trong tài liệu Gson

Hữu ích 592 Chia sẻ Viết bình luận 5
Không hữu ích

Một điều cần lưu ý là các hiệu ứng thoáng qua cả tuần tự hóa và giải tuần tự hóa. Nó cũng sẽ phát ra giá trị từ được tuần tự hóa vào đối tượng, ngay cả khi nó có trong JSON.

Hữu ích 32 · Không hữu ích · Trả lời 0

Cách tiếp cận này không hiệu quả với tôi, vì nó không chỉ loại trừ trường khỏi tuần tự hóa gson, mà còn loại trừ trường khỏi tuần tự hóa ứng dụng nội bộ (sử dụng giao diện Nối tiếp).

Hữu ích 11 · Không hữu ích · Trả lời 0

thoáng qua ngăn chặn SERIALIZATION và MÔ TẢ một lĩnh vực. Điều này không phù hợp với nhu cầu của tôi.

Hữu ích 8 · Không hữu ích · Trả lời 0

nó gần giống như một chú thích loại trừ như trong nó áp dụng cho tất cả các phiên bản của lớp đó. Tôi muốn loại trừ năng động thời gian chạy. Tôi một số trường hợp tôi muốn một số trường bị loại trừ để cung cấp phản hồi nhẹ hơn / bị hạn chế và trong các trường hợp khác tôi muốn toàn bộ đối tượng được tuần tự hóa

Hữu ích 4 · Không hữu ích · Trả lời 0

Vấn đề với việc sử dụng transientthay vì @Exposelà bạn vẫn phải giả lập POJO trên máy khách của mình với tất cả các trường có thể có thể tham gia. Trong trường hợp API back-end có thể được chia sẻ giữa các dự án, trường hợp này có thể có vấn đề các lĩnh vực bổ sung được thêm vào. Về cơ bản, nó là danh sách trắng so với danh sách đen của các lĩnh vực.

Hữu ích 3 · Không hữu ích · Trả lời 0

300
Phan Kiều Trinh
8 năm trước

Nishant cung cấp một giải pháp tốt, nhưng có một cách dễ dàng hơn. Chỉ cần đánh dấu các trường mong muốn bằng chú thích @Expose, chẳng hạn như:

@Expose private Long id;

Để lại bất kỳ trường nào mà bạn không muốn tuần tự hóa. Sau đó, chỉ cần tạo đối tượng Gson của bạn theo cách này:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Hữu ích 300 Chia sẻ Viết bình luận 5
Không hữu ích

Có thể có một cái gì đó như "notExpose" và chỉ bỏ qua những cái đó cho trường hợp tất cả ngoại trừ một trường phải được tuần tự hóa và thêm chú thích cho tất cả chúng là dư thừa?

Hữu ích 90 · Không hữu ích · Trả lời 0

@DaSh Gần đây tôi có một kịch bản như vậy. Rất dễ dàng để viết một ExinatingStrargety tùy chỉnh đã làm chính xác điều đó. Xem câu trả lời của Nishant. Vấn đề duy nhất là bao gồm một loạt các lớp container và fiddle với Skipgroup vs Skipfield (các trường có thể là các lớp ...)

Hữu ích 2 · Không hữu ích · Trả lời 0

@DaSh Câu trả lời của tôi dưới đây thực hiện chính xác điều đó.

Hữu ích 1 · Không hữu ích · Trả lời 0

@Danlil Bạn sẽ có thể sử dụng @Expose (serialize = false, deserialize = false)

Hữu ích 1 · Không hữu ích · Trả lời 0

Thật là một giải pháp tuyệt vời. Tôi đã chạy vào một kịch bản mà tôi muốn một trường được tuần tự hóa vào đĩa nhưng bị bỏ qua khi gửi nó đến một máy chủ thông qua gson. Hoàn hảo, cảm ơn!

Hữu ích 0 · Không hữu ích · Trả lời 0

220
Tạ Huy Tâm
9 năm trước

Vì vậy, bạn muốn loại trừ firstNamecountry.name. Đây là những gì bạn ExclusionStrategynên trông như thế nào

    public class TestExclStrat implements ExclusionStrategy {

        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {

            return (f.getDeclaringClass() == Student.class && f.getName().equals("firstName"))||
            (f.getDeclaringClass() == Country.class && f.getName().equals("name"));
        }

    }

Nếu bạn thấy chặt chẽ nó sẽ trả về truecho Student.firstNameCountry.name, đó là những gì bạn muốn loại trừ.

Bạn cần áp dụng ExclusionStrategynhư thế này,

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new TestExclStrat())
        //.serializeNulls() <-- uncomment to serialize NULL fields as well
        .create();
    Student src = new Student();
    String json = gson.toJson(src);
    System.out.println(json);

Điều này trả về:

{"middleName": "J.", "tên viết tắt": "PF", "lastName": "Fry", "country": {"id": 91}}

Tôi giả sử đối tượng quốc gia được khởi tạo id = 91Ltrong lớp học sinh.


Bạn có thể nhận được ưa thích. Ví dụ: bạn không muốn tuần tự hóa bất kỳ trường nào có chứa chuỗi "tên" trong tên của nó. Làm cái này:

public boolean shouldSkipField(FieldAttributes f) {
    return f.getName().toLowerCase().contains("name"); 
}

Điều này sẽ trở lại:

{ "initials": "P.F", "country": { "id": 91 }}

EDIT: Đã thêm thông tin theo yêu cầu.

Điều này ExclusionStrategysẽ làm điều đó, nhưng bạn cần phải vượt qua "Tên trường đủ điều kiện". Xem bên dưới:

    public class TestExclStrat implements ExclusionStrategy {

        private Class<?> c;
        private String fieldName;
        public TestExclStrat(String fqfn) throws SecurityException, NoSuchFieldException, ClassNotFoundException
        {
            this.c = Class.forName(fqfn.substring(0, fqfn.lastIndexOf(".")));
            this.fieldName = fqfn.substring(fqfn.lastIndexOf(".")+1);
        }
        public boolean shouldSkipClass(Class<?> arg0) {
            return false;
        }

        public boolean shouldSkipField(FieldAttributes f) {

            return (f.getDeclaringClass() == c && f.getName().equals(fieldName));
        }

    }

Đây là cách chúng ta có thể sử dụng nó một cách khái quát.

    Gson gson = new GsonBuilder()
        .setExclusionStrategies(new TestExclStrat("in.naishe.test.Country.name"))
        //.serializeNulls()
        .create();
    Student src = new Student();
    String json = gson.toJson(src);
    System.out.println(json); 

Nó trở lại:

{ "firstName": "Philip" , "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91 }}
Hữu ích 220 Chia sẻ Viết bình luận 5
Không hữu ích

Câu trả lời này nên được đánh dấu là câu trả lời ưa thích. Không giống như các câu trả lời khác hiện đang có nhiều phiếu bầu hơn, giải pháp này không yêu cầu bạn phải sửa đổi lớp bean. Đây là một điểm cộng rất lớn. Điều gì xảy ra nếu người khác đang sử dụng cùng một lớp bean và bạn đã đánh dấu một trường mà họ muốn duy trì là "tạm thời"?

Hữu ích 11 · Không hữu ích · Trả lời 0

Cảm ơn bạn đã trả lời. Điều tôi muốn là tạo ra một country.nameEx LoạiStrargety có thể lấy một chuỗi như và chỉ loại trừ trường namekhi tuần tự hóa trường country. Nó phải đủ chung chung để áp dụng cho mọi lớp có thuộc tính có tên là quốc gia của lớp Quốc gia. Tôi không muốn tạo Ex Loại trừ Chiến lược cho mọi lớp học

Hữu ích 0 · Không hữu ích · Trả lời 0

@Liviu T. Tôi đã cập nhật câu trả lời. Đó là cách tiếp cận chung chung. Bạn có thể thậm chí còn sáng tạo hơn, nhưng tôi giữ nó nguyên tố.

Hữu ích 0 · Không hữu ích · Trả lời 0

Ty để cập nhật. Những gì tôi đang cố gắng xem liệu có thể biết tôi đang ở đâu trong biểu đồ đối tượng khi phương thức được gọi để tôi có thể loại trừ một số trường của quốc gia nhưng không phải là countryOfBirth (ví dụ) cùng một lớp nhưng thuộc tính khác nhau. Tôi đã chỉnh sửa câu hỏi của mình để làm rõ những gì tôi đang cố gắng đạt được

Hữu ích 0 · Không hữu ích · Trả lời 0

Có cách nào để loại trừ các trường có giá trị trống không?

Hữu ích 0 · Không hữu ích · Trả lời 0

194
Dương Hoài Việt
5 năm trước

Sau khi đọc tất cả các câu trả lời có sẵn, tôi phát hiện ra rằng, linh hoạt nhất, trong trường hợp của tôi, là sử dụng @Excludechú thích tùy chỉnh . Vì vậy, tôi đã thực hiện chiến lược đơn giản cho việc này (tôi không muốn đánh dấu tất cả các trường bằng cách sử dụng @Exposecũng như tôi không muốn sử dụng transientxung đột trong Serializabletuần tự hóa ứng dụng ):

Chú thích:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}

Chiến lược:

public class AnnotationExclusionStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getAnnotation(Exclude.class) != null;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}

Sử dụng:

new GsonBuilder().setExclusionStrategies(new AnnotationExclusionStrategy()).create();
Hữu ích 194 Chia sẻ Viết bình luận 5
Không hữu ích

Như một lưu ý bổ sung, nếu bạn muốn sử dụng chiến lược loại trừ của mình chỉ để tuần tự hóa hoặc chỉ addSerializationExclusionStrategyaddDeserializationExclusionStrategysetExclusionStrategies

Hữu ích 13 · Không hữu ích · Trả lời 0

Hoàn hảo! Giải pháp tạm thời không hiệu quả với tôi vì tôi đang sử dụng Realm cho DB và tôi muốn loại trừ một trường chỉ từ Gson, nhưng không phải Realm (tạm thời không hoạt động)

Hữu ích 9 · Không hữu ích · Trả lời 0

Tuyệt vời khi bạn không thể sử dụng transientvì nhu cầu của các thư viện khác. Cảm ơn!

Hữu ích 3 · Không hữu ích · Trả lời 0

Đây phải là câu trả lời được chấp nhận. Để bỏ qua các trường null, chỉ cần thay đổi f.getAnnotation(Exclude.class) != nullthànhf.getAnnotation(Exclude.class) == null

Hữu ích 2 · Không hữu ích · Trả lời 0

Cũng tuyệt vời đối với tôi vì Android tuần tự hóa các lớp của tôi giữa các hoạt động, nhưng tôi chỉ muốn loại trừ chúng khi tôi sử dụng GSON. Điều này hãy để ứng dụng của tôi tiếp tục hoạt động theo cùng một cách cho đến khi nó muốn gói chúng lại để gửi cho người khác.

Hữu ích 1 · Không hữu ích · Trả lời 0

75
Lý Anh Tú
6 năm trước

Tôi gặp phải vấn đề này, trong đó tôi có một số ít trường tôi chỉ muốn loại trừ khỏi việc xê-ri hóa, vì vậy tôi đã phát triển một giải pháp khá đơn giản sử dụng @Exposechú thích của Gson với các chiến lược loại trừ tùy chỉnh.

Cách tích hợp duy nhất để sử dụng @Exposelà bằng cách cài đặt GsonBuilder.excludeFieldsWithoutExposeAnnotation(), nhưng như tên cho biết, các trường không có tường minh @Exposesẽ bị bỏ qua. Vì tôi chỉ có một vài lĩnh vực mà tôi muốn loại trừ, tôi thấy triển vọng của việc thêm chú thích vào mọi lĩnh vực rất cồng kềnh.

Tôi thực sự muốn nghịch đảo, trong đó mọi thứ được bao gồm trừ khi tôi sử dụng rõ ràng @Exposeđể loại trừ nó. Tôi đã sử dụng các chiến lược loại trừ sau đây để thực hiện điều này:

new GsonBuilder()
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                final Expose expose = fieldAttributes.getAnnotation(Expose.class);
                return expose != null && !expose.serialize();
            }

            @Override
            public boolean shouldSkipClass(Class<?> aClass) {
                return false;
            }
        })
        .addDeserializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fieldAttributes) {
                final Expose expose = fieldAttributes.getAnnotation(Expose.class);
                return expose != null && !expose.deserialize();
            }

            @Override
            public boolean shouldSkipClass(Class<?> aClass) {
                return false;
            }
        })
        .create();

Bây giờ tôi có thể dễ dàng loại trừ một vài trường có @Expose(serialize = false)hoặc @Expose(deserialize = false)chú thích (lưu ý rằng giá trị mặc định cho cả hai @Exposethuộc tính là true). Tất nhiên bạn có thể sử dụng @Expose(serialize = false, deserialize = false), nhưng điều đó được thực hiện chính xác hơn bằng cách khai báo trường transientthay thế (điều này vẫn có hiệu lực với các chiến lược loại trừ tùy chỉnh này).

Hữu ích 75 Chia sẻ Viết bình luận 3
Không hữu ích

@paiego Bạn có thể mở rộng về điều đó? Bây giờ tôi đã bị loại bỏ khỏi việc sử dụng Gson nhiều năm và tôi không hiểu tại sao chú thích lại hiệu quả hơn là đánh dấu nó thoáng qua.

Hữu ích 1 · Không hữu ích · Trả lời 0

Để hiệu quả, tôi có thể thấy một trường hợp sử dụng @Expose (serialize = false, deserialize = false) thay vì tạm thời.

Hữu ích 0 · Không hữu ích · Trả lời 0

Ahh, tôi đã làm sai, cảm ơn vì đã nắm bắt điều này. Tôi nhầm tưởng dễ bay hơi cho thoáng qua. (ví dụ: Không có bộ nhớ đệm và do đó không có vấn đề liên kết bộ đệm với tính dễ bay hơi, nhưng nó ít hiệu năng hơn)

Hữu ích 0 · Không hữu ích · Trả lời 0

16
Tạ Mai Khôi
8 năm trước

Tôi đã đưa ra một nhà máy lớp để hỗ trợ chức năng này. Vượt qua trong bất kỳ kết hợp của một trong hai lĩnh vực hoặc các lớp bạn muốn loại trừ.

public class GsonFactory {

    public static Gson build(final List<String> fieldExclusions, final List<Class<?>> classExclusions) {
        GsonBuilder b = new GsonBuilder();
        b.addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                return fieldExclusions == null ? false : fieldExclusions.contains(f.getName());
            }

            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                return classExclusions == null ? false : classExclusions.contains(clazz);
            }
        });
        return b.create();

    }
}

Để sử dụng, hãy tạo hai danh sách (mỗi danh sách là tùy chọn) và tạo đối tượng GSON của bạn:

static {
 List<String> fieldExclusions = new ArrayList<String>();
 fieldExclusions.add("id");
 fieldExclusions.add("provider");
 fieldExclusions.add("products");

 List<Class<?>> classExclusions = new ArrayList<Class<?>>();
 classExclusions.add(Product.class);
 GSON = GsonFactory.build(null, classExclusions);
}

private static final Gson GSON;

public String getSomeJson(){
    List<Provider> list = getEntitiesFromDatabase();
    return GSON.toJson(list);
}
Hữu ích 16 Chia sẻ Viết bình luận 2
Không hữu ích

Tất nhiên, điều này có thể được sửa đổi để xem xét tên đầy đủ của thuộc tính và loại trừ điều đó khi khớp ...

Hữu ích 0 · Không hữu ích · Trả lời 0

Tôi đang làm ví dụ dưới đây. Đây không phải là làm việc. Xin đề nghị tĩnh cuối cùng Gson GSON; tĩnh {Danh sách <String> fieldExinating = new ArrayList <String> (); trườngExinating.add ("id"); GSON = GsonFactory.build (trườngExjection, null); } Chuỗi tĩnh riêng getSomeJson () {String jsonStr = "[{\" id \ ": 111, \" name \ ": \" Praveen \ ", \" age \ ": 16}, {\" id \ ": 222, \ "tên \": \ "prashant \", \ "tuổi \": 20}] "; trả về jsonStr; } static static void main (String [] args) {String jsonStr = getSomeJson (); System.out.println (GSON.toJson (jsonStr)); }

Hữu ích 0 · Không hữu ích · Trả lời 0

16
Tạ Hải San
6 năm trước

Bạn có thể khám phá cây json với gson.

Hãy thử một cái gì đó như thế này:

gson.toJsonTree(student).getAsJsonObject()
.get("country").getAsJsonObject().remove("name");

Bạn cũng có thể thêm một số thuộc tính:

gson.toJsonTree(student).getAsJsonObject().addProperty("isGoodStudent", false);

Đã thử nghiệm với gson 2.2.4.

Hữu ích 16 Chia sẻ Viết bình luận 2
Không hữu ích

Tôi tự hỏi liệu đây có phải là quá nhiều hiệu suất nếu bạn muốn loại bỏ một thuộc tính phức tạp phải được phân tích cú pháp trước khi loại bỏ. Suy nghĩ?

Hữu ích 2 · Không hữu ích · Trả lời 0

Chắc chắn không phải là một giải pháp có thể mở rộng, hãy tưởng tượng tất cả những vấn đề đau đầu bạn sẽ phải trải qua nếu bạn thay đổi cấu trúc của đối tượng hoặc thêm / xóa công cụ.

Hữu ích 0 · Không hữu ích · Trả lời 0

13
Hoàng Vĩnh Khang
3 năm trước

Tôi đã giải quyết vấn đề này với các chú thích tùy chỉnh. Đây là lớp chú thích "SkipSerialisation" của tôi:

@Target (ElementType.FIELD)
public @interface SkipSerialisation {

}

và đây là GsonBuilder của tôi:

gsonBuilder.addSerializationExclusionStrategy(new ExclusionStrategy() {

  @Override public boolean shouldSkipField (FieldAttributes f) {

    return f.getAnnotation(SkipSerialisation.class) != null;

  }

  @Override public boolean shouldSkipClass (Class<?> clazz) {

    return false;
  }
});

Thí dụ :

public class User implements Serializable {

  public String firstName;

  public String lastName;

  @SkipSerialisation
  public String email;
}
Hữu ích 13 Chia sẻ Viết bình luận 2
Không hữu ích

Gson: Cách loại trừ các trường cụ thể khỏi Tuần tự hóa mà không cần chú thích

Hữu ích 5 · Không hữu ích · Trả lời 0

Bạn cũng nên thêm @Retention(RetentionPolicy.RUNTIME)vào chú thích của bạn.

Hữu ích 3 · Không hữu ích · Trả lời 0

8
Vũ Nguyết Ánh
7 năm trước

Hoặc có thể nói trường whats sẽ không hiển thị với:

Gson gson = gsonBuilder.excludeFieldsWithModifiers(Modifier.TRANSIENT).create();

trên lớp của bạn trên thuộc tính:

private **transient** boolean nameAttribute;
Hữu ích 8 Chia sẻ Viết bình luận 1
Không hữu ích

Các trường tạm thời và tĩnh được loại trừ theo mặc định; không cần phải gọi excludeFieldsWithModifiers()cho điều đó.

Hữu ích 16 · Không hữu ích · Trả lời 0

7
Đặng Việt Hùng
3 năm trước

Tôi đã sử dụng chiến lược này: tôi đã loại trừ mọi trường không được đánh dấu bằng chú thích @SerializedName , tức là:

public class Dummy {

    @SerializedName("VisibleValue")
    final String visibleValue;
    final String hiddenValue;

    public Dummy(String visibleValue, String hiddenValue) {
        this.visibleValue = visibleValue;
        this.hiddenValue = hiddenValue;
    }
}


public class SerializedNameOnlyStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return f.getAnnotation(SerializedName.class) == null;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}


Gson gson = new GsonBuilder()
                .setExclusionStrategies(new SerializedNameOnlyStrategy())
                .create();

Dummy dummy = new Dummy("I will see this","I will not see this");
String json = gson.toJson(dummy);

Nó trở lại

{"VisibleValue": "Tôi sẽ thấy điều này"}

Hữu ích 7 Chia sẻ Viết bình luận 0
Không hữu ích

6
Phạm Khánh Vy
4 năm trước

Một cách tiếp cận khác (đặc biệt hữu ích nếu bạn cần đưa ra quyết định loại trừ một trường khi chạy) là đăng ký TypeAd CHƯƠNG với ví dụ gson của bạn. Ví dụ dưới đây:

Gson gson = new GsonBuilder()
.registerTypeAdapter(BloodPressurePost.class, new BloodPressurePostSerializer())

Trong trường hợp dưới đây, máy chủ sẽ mong đợi một trong hai giá trị nhưng vì cả hai đều là số nguyên nên gson sẽ tuần tự hóa cả hai. Mục tiêu của tôi là bỏ qua bất kỳ giá trị nào bằng 0 (hoặc ít hơn) từ json được đăng lên máy chủ.

public class BloodPressurePostSerializer implements JsonSerializer<BloodPressurePost> {

    @Override
    public JsonElement serialize(BloodPressurePost src, Type typeOfSrc, JsonSerializationContext context) {
        final JsonObject jsonObject = new JsonObject();

        if (src.systolic > 0) {
            jsonObject.addProperty("systolic", src.systolic);
        }

        if (src.diastolic > 0) {
            jsonObject.addProperty("diastolic", src.diastolic);
        }

        jsonObject.addProperty("units", src.units);

        return jsonObject;
    }
}
Hữu ích 6 Chia sẻ Viết bình luận 0
Không hữu ích

2
Hoàng Ngọc Yến
1 năm trước

@TransientChú thích của Kotlin cũng thực hiện thủ thuật này.

data class Json(
    @field:SerializedName("serialized_field_1") val field1: String,
    @field:SerializedName("serialized_field_2") val field2: String,
    @Transient val field3: String
)

Đầu ra:

{"serialized_field_1":"VALUE1","serialized_field_2":"VALUE2"}
Hữu ích 2 Chia sẻ Viết bình luận 0
Không hữu ích

1
Trần Oanh Thơ
3 năm trước

Tôi đang làm việc chỉ bằng cách đặt @Exposechú thích, đây là phiên bản mà tôi sử dụng

compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

Trong Modellớp:

@Expose
int number;

public class AdapterRestApi {

Trong Adapterlớp:

public EndPointsApi connectRestApi() {
    OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(90000, TimeUnit.SECONDS)
            .readTimeout(90000,TimeUnit.SECONDS).build();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(ConstantRestApi.ROOT_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build();

    return retrofit.create  (EndPointsApi.class);
}
Hữu ích 1 Chia sẻ Viết bình luận 0
Không hữu ích

1
Ngô Nhật Hồng
1 năm trước

Tôi có phiên bản Kotlin

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
internal annotation class JsonSkip

class SkipFieldsStrategy : ExclusionStrategy {

    override fun shouldSkipClass(clazz: Class<*>): Boolean {
        return false
    }

    override fun shouldSkipField(f: FieldAttributes): Boolean {
        return f.getAnnotation(JsonSkip::class.java) != null
    }
}

và cách bạn có thể thêm phần này vào Retrofit GSONConverterFactory:

val gson = GsonBuilder()
                .setExclusionStrategies(SkipFieldsStrategy())
                //.serializeNulls()
                //.setDateFormat(DateFormat.LONG)
                //.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
                //.setPrettyPrinting()
                //.registerTypeAdapter(Id.class, IdTypeAdapter())
                .create()
        return GsonConverterFactory.create(gson)
Hữu ích 1 Chia sẻ Viết bình luận 0
Không hữu ích

0
Lý Kim Khánh
1 năm trước

Đây là những gì tôi luôn luôn sử dụng:

Hành vi mặc định được triển khai trong Gson là các trường đối tượng null bị bỏ qua.

Có nghĩa là đối tượng Gson không tuần tự hóa các trường có giá trị null thành JSON. Nếu một trường trong một đối tượng Java là null, Gson sẽ loại trừ nó.

Bạn có thể sử dụng chức năng này để chuyển đổi một số đối tượng thành null hoặc do chính bạn thiết lập

     /**
   * convert object to json
   */
  public String toJson(Object obj) {
    // Convert emtpy string and objects to null so we don't serialze them
    setEmtpyStringsAndObjectsToNull(obj);
    return gson.toJson(obj);
  }

  /**
   * Sets all empty strings and objects (all fields null) including sets to null.
   *
   * @param obj any object
   */
  public void setEmtpyStringsAndObjectsToNull(Object obj) {
    for (Field field : obj.getClass().getDeclaredFields()) {
      field.setAccessible(true);
      try {
        Object fieldObj = field.get(obj);
        if (fieldObj != null) {
          Class fieldType = field.getType();
          if (fieldType.isAssignableFrom(String.class)) {
            if(fieldObj.equals("")) {
              field.set(obj, null);
            }
          } else if (fieldType.isAssignableFrom(Set.class)) {
            for (Object item : (Set) fieldObj) {
              setEmtpyStringsAndObjectsToNull(item);
            }
            boolean setFielToNull = true;
            for (Object item : (Set) field.get(obj)) {
              if(item != null) {
                setFielToNull = false;
                break;
              }
            }
            if(setFielToNull) {
              setFieldToNull(obj, field);
            }
          } else if (!isPrimitiveOrWrapper(fieldType)) {
            setEmtpyStringsAndObjectsToNull(fieldObj);
            boolean setFielToNull = true;
            for (Field f : fieldObj.getClass().getDeclaredFields()) {
              f.setAccessible(true);
              if(f.get(fieldObj) != null) {
                setFielToNull = false;
                break;
              }
            }
            if(setFielToNull) {
              setFieldToNull(obj, field);
            }
          }
        }
      } catch (IllegalAccessException e) {
        System.err.println("Error while setting empty string or object to null: " + e.getMessage());
      }
    }
  }

  private void setFieldToNull(Object obj, Field field) throws IllegalAccessException {
    if(!Modifier.isFinal(field.getModifiers())) {
      field.set(obj, null);
    }
  }

  private boolean isPrimitiveOrWrapper(Class fieldType)  {
    return fieldType.isPrimitive()
        || fieldType.isAssignableFrom(Integer.class)
        || fieldType.isAssignableFrom(Boolean.class)
        || fieldType.isAssignableFrom(Byte.class)
        || fieldType.isAssignableFrom(Character.class)
        || fieldType.isAssignableFrom(Float.class)
        || fieldType.isAssignableFrom(Long.class)
        || fieldType.isAssignableFrom(Double.class)
        || fieldType.isAssignableFrom(Short.class);
  }
Hữu ích 0 Chia sẻ Viết bình luận 0
Không hữu ích

Trả lời của bạn

Xem trước nội dung