简体   繁体   中英

GSON - print all fields that are annotated as deserialized=true

I have a Java EE project that is using GSON library (Google's library for processing of JSON objects).

In my entity classes I use @Expose annotation to control which fields are considered by GSON. I also use serialize/deserialize properties on that annotation to control which fields are considered when serializing a Java object to JSON and which fields are considered when deserializing JSON objects to Java objects. For example:

public class Movie {

   @Expose(serialize=true, deserialize=false)
   @Id
   @GeneratedValue
   private long id;

   @Expose(serialize=true, deserialize=true)
   private String name;

   @Expose(serialize=true, deserialize=true)
   private String genre;

   @Expose(serialize=false, deserialize=true)
   private String secretID;

}

Here when I send the JSON object to be deserialized into Java object I send an object like this:

{
   "name": "Memento",
   "genre": "thriller",
   "secretID": "123asd"
}

And, when I serialize Java object to JSON I get something like this:

{
   "id": 1,
   "name": "Memento",
   "genre": "thriller"
}

I have this Java code:

public static void main(String[] args) {

    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
    String json = gson.toJson(new Movie());
    System.out.println(json);
}

that generates this as it's output:

{
   "id": 0,
   "name": "",
   "genre": ""
}

Those are fields that are marked to be serialized. However, what if I need to print out all of the fields that are marked to be deserialized, so that I can easier create a JSON object that will be used as input when creating new Movies.

The desired output is this:

{
   "name": "",
   "genre": "",
   "secretID": ""
}

Note: I don't want to change serialize/deserialize properties on @Expose annotations because they are set to how my application needs to work. I just need an easy way to generate a template JSON objects that will be used as input to my application, so I don't have to type it manually.

You could implement more generic ExclusionStrategy like:

@RequiredArgsConstructor
public class IncludeListedFields implements ExclusionStrategy {
    @NonNull
    private Set<String> fieldsToInclude;
    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return ! fieldsToInclude.contains(f.getName());
    }
    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}

then use it like:

Set<String> fieldsToInclude =
        new HashSet<>(Arrays.asList("name", "genre", "secretID"));        
ExclusionStrategy es = new IncludeListedFields(fieldsToInclude);
Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls()
                    .addSerializationExclusionStrategy(es).create();

Note following things:

  • You should not now use the builder method .excludeFieldsWithoutExposeAnnotation .
  • By default Gson does not serialize fileds with null values so you need to use builder method .serializeNulls() . This does not generate Json with string values "" but just null .
  • In your example Json fields contained empty strings as values but you did not introduce default constructor Movie() that would initialize field values to empty strings so they remain null . But if you initialize them - say to empty string "" - then they are not null & you do not need to use builder method .serializeNulls() .

BUT if you really need and want only to serialize based on @Expose(deserialize=true) then the ExclusionStrategy can be just:

public class PrintDeserializeTrue implements ExclusionStrategy {
    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        Expose annotationExpose = f.getAnnotation(Expose.class);
        if(null != annotationExpose) {
            if(annotationExpose.deserialize())
                return false;
        }
        return true;
    }
    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM