Gson: How to exclude specific fields from Serialization without annotations

后端 未结 15 1431
后悔当初
后悔当初 2020-11-22 05:39

I\'m trying to learn Gson and I\'m struggling with field exclusion. Here are my classes

public class Student {    
  private Long                id;
  privat         


        
相关标签:
15条回答
  • 2020-11-22 06:06

    I came up with a class factory to support this functionality. Pass in any combination of either fields or classes you want to exclude.

    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();
    
        }
    }
    

    To use, create two lists (each is optional), and create your GSON object:

    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);
    }
    
    0 讨论(0)
  • 2020-11-22 06:06

    I solved this problem with custom annotations. This is my "SkipSerialisation" Annotation class:

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

    and this is my GsonBuilder:

    gsonBuilder.addSerializationExclusionStrategy(new ExclusionStrategy() {
    
      @Override public boolean shouldSkipField (FieldAttributes f) {
    
        return f.getAnnotation(SkipSerialisation.class) != null;
    
      }
    
      @Override public boolean shouldSkipClass (Class<?> clazz) {
    
        return false;
      }
    });
    

    Example :

    public class User implements Serializable {
    
      public String firstName;
    
      public String lastName;
    
      @SkipSerialisation
      public String email;
    }
    
    0 讨论(0)
  • 2020-11-22 06:13

    I have Kotlin version

    @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
        }
    }
    

    and how You can add this to 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)
    
    0 讨论(0)
  • 2020-11-22 06:15

    Any fields you don't want serialized in general you should use the "transient" modifier, and this also applies to json serializers (at least it does to a few that I have used, including gson).

    If you don't want name to show up in the serialized json give it a transient keyword, eg:

    private transient String name;
    

    More details in the Gson documentation

    0 讨论(0)
  • 2020-11-22 06:15

    Kotlin's @Transientannotation also does the trick apparently.

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

    Output:

    {"serialized_field_1":"VALUE1","serialized_field_2":"VALUE2"}
    
    0 讨论(0)
  • 2020-11-22 06:19

    I'm working just by putting the @Expose annotation, here my version that I use

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

    In Model class:

    @Expose
    int number;
    
    public class AdapterRestApi {
    

    In the Adapter class:

    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);
    }
    
    0 讨论(0)
提交回复
热议问题