0

I'm using Spring with Gson to object serialization.

I have model objects that use @Expose annotation e.g.:

public class Zone {
    @Expose
    private String name;
    @Expose
    private String description;
    @Expose
    private List<String> longList;

    private String someIrrelevantVar;
}

I'm have 2 controllers which serves Zone objects list to user e.g.:

@RestController
class ZoneController {
    @GetMapping(value = "fullData")
    List<Zone> getFullZones() {
        return zoneService.getZones();
    }
}

@RestController
class SimpleZoneController {
    @GetMapping(value = "simpleData")
    List<Zone> getSimpleZones() {
        return zoneService.getZones();
    }
}

The problem is List<String> longList var - it usually has a lot of entries (String is only example, in code it could be complex object).

In my getFullZones() I want to serve to user zones with this longList but in getSimpleZones() I want ot serve zones without longList (it's not used in any way on the client side).

How to do that?

I could iterate list with zones and set longList to null but it's not very elegant solution.

I'm setting up Spring to use Gson like this:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(createGsonHttpMessageConverter());
        super.configureMessageConverters(converters);
    }
    private GsonHttpMessageConverter createGsonHttpMessageConverter() {
        Gson gson = new GsonBuilder()
                .excludeFieldsWithoutExposeAnnotation()
                //.registerTypeAdapter - register some deserializers
                .create();
        GsonHttpMessageConverter gsonConverter = new GsonHttpMessageConverter();
        gsonConverter.setGson(gson);

        return gsonConverter;
    }
}
user3626048
  • 706
  • 4
  • 19
  • 52

1 Answers1

0

Create a base class ZoneSimple and extend another class Zone extends ZoneSimple. Move the @Expose from fields to methods.

In the base class the method has no annotation. In the Zone the method is annotated.

Alternatively you can add a ProxyZone class which keeps zone instance and delegates all the calls to the instance. Annotate the Proxy as you need.

Another way is

 Gson gson = new GsonBuilder()
        .addSerializationExclusionStrategy(new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes f) {
                return f.getName().toLowerCase().contains("fieldName");
            }

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

Got from the answer

StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • The `@Expose` is applicable only to fields, not methods. Could you explain solution with `ProxyZone`? How the third solution could work in my case? – user3626048 Aug 08 '17 at 12:58
  • Sorry I miss that @Expose is applied to fields only. Then you can try the `addSerializationExclusionStrategy` based approach – StanislavL Aug 08 '17 at 13:02
  • but how to use `ExclusionStrategy` in this case? I have only one instance of `Gson` (created in `WebMvcConfigurerAdapter`) and if I add there `ExclusionStrategy` for certain fields for `Zone` class it will effect anywhere. Or should I create new `Gson` instance in my `getSimpleZones()` method and add `ExclusionStrategy` there? – user3626048 Aug 09 '17 at 10:00
  • Create the GsonBuilder on fly rather than use autowired. – StanislavL Aug 09 '17 at 10:29
  • I didn't mean `@Autowired` Gson but Gson registered as `HttpMessageConverter` used by default when serializing any data – user3626048 Aug 09 '17 at 13:21
  • Then just create 2 different classes – StanislavL Aug 09 '17 at 13:28