1

I've seen examples on SO of excluding fields from serialization at runtime. I need to do that, but I'd like to have Gson handle serialization of all the fields not being excluded.

The complicating part is that I can't have Gson do the serialization first, then have a TypeAdapter modify the result. I need to somehow do the exclusion first, then have what remains be serialized. Is this even possible?

Julian A.
  • 10,928
  • 16
  • 67
  • 107
  • Correct me if I'm wrong, but a TypeAdapter is what is doing the serialization, it wouldn't be modifying the result since it itself is forming the result (JSON) as it goes, no? – nickb Dec 02 '15 at 11:18
  • @nickb I've seen an example on SO where default serialization was delegated by a TypeAdapter to the library, then the result was edited by the TypeAdapter to remove the excluded fields before returning the final result. – Julian A. Dec 02 '15 at 15:49
  • 1
    Interesting, do you have the link? It'd probably help better explain your question if you could provide the implementation you're describing along with an explanation of its shortcomings. – nickb Dec 02 '15 at 15:58
  • @nickb I figured something out. But thanks for responding. – Julian A. Dec 03 '15 at 06:14

1 Answers1

0

Ok, with some experimentation, and this helpful post, I was able to cobble together a way to conditionally exclude mocked fields.

The reason I'm going to all this trouble is that out-of-the-box Gson throws an exception when it encounters Spock-mocked fields.

For Spock, my check to determine if a field is mocked is to see if the class name of the value it references contains the substring EnhancerByCGLib.

Below, ResizingArrayQueueOfStrings.arrayFactory is the field that may, or may not, be mocked.

Thankfully, I can use a single JsonSerializer for all classes that need this sort of treatment. Ideally, I wouldn't have to register the serializer for every class that might be mocked... but that's a battle for another day.

The resulting JSON, when the field is mocked and ResizingArrayQueueOfStrings is serialized, is

queue {
  "arrayFactory": "** mocked **",     
}

otherwise, it's

queue {
  "arrayFactory": {},
}

Hope this helps others with a similar need.

public class MockSerializer implements JsonSerializer<Object> {

    @Override
    public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
        Gson gson = new Gson();
        String className = src.getClass().getName();
        boolean isMocked = className.contains("EnhancerByCGLIB");
        if (isMocked) return new JsonPrimitive("** mocked **");
        else return gson.toJsonTree(src);
    }

}

public class ResizingArrayQueueOfStrings {

    private ArrayFactory arrayFactory;

    public String toString() {
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(ArrayFactory.class, new MockSerializer())
                .setPrettyPrinting()
                .create();
        return gson.toJson(this);
    }

}
Community
  • 1
  • 1
Julian A.
  • 10,928
  • 16
  • 67
  • 107