Atharva
Atharva

Reputation: 6969

Excluding certain fields from Serialization based on value in GSON

I am using GSON for my serialization purposes, I am not finding a way of excluding certain fields from serialization based on ExclusionStrategy class provided by Gson based on the value of field, as it only supports top level class or field attributes based exclusions. The field attributes do not include the value of that field. So what should I do?

Upvotes: 10

Views: 11726

Answers (3)

Dabbler
Dabbler

Reputation: 9873

This is how I use a type adapter to avoid serializing boolean values that are false. It avoids creating an additional Gson instance and does not rely on specific field names.

class MyClassTypeAdapter: JsonSerializer<MyClass>{
   override fun serialize(myObject: MyClass, type: Type, context: JsonSerializationContext): JsonElement {
      val jsonElement = context.serialize(myObject)

      jsonElement.asJsonObject.entrySet().removeAll { it.value is JsonPrimitive && (it.value as JsonPrimitive).isBoolean && !it.value.asBoolean }

      return jsonElement
   }
}

Upvotes: 1

Atharva
Atharva

Reputation: 6969

The way to achieve this is by creating custom serializer for the class in question. After allowing Gson to create a JSON object in default fashion, remove the property that you want to exclude based on its value.

public class SerializerForMyClass implements JsonSerializer<MyClass> {  

    @Override
    public JsonElement serialize(MyClass obj, Type type, JsonSerializationContext jsc) {
        Gson gson = new Gson();
        JsonObject jObj = (JsonObject)gson.toJsonTree(obj);   
        if(obj.getMyProperty()==0){
            jObj.remove("myProperty");
        }
        return jObj;
    }
}

And registering the new serializer in the Gson object that you use for serialization in the application for this class.

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MyClass.class, new SerializerForMyClass());
Gson gson=gsonBuilder.create();
gson.toJson(myObjectOfTypeMyClass);

Upvotes: 22

Marshall
Marshall

Reputation: 51

Here's a more in depth example of a class I wrote to remove all false booleans as well as all "false" strings. It was thrown together pretty quickly but seems to work ok. Let me know if there are any bugs you find.

public class RemoveFalseJsonSerializer implements JsonSerializer<Object> {

//~ Methods --------------------------------------------------------------------------------------------------------

/**
 * serialize
 *
 * @param object in value
 * @param type in value
 * @param jsonSerializationContext in value
 *
 * @return out value
 */
@Override
public JsonElement serialize(Object object, Type type, JsonSerializationContext jsonSerializationContext) {
    Gson gson = new Gson();
    JsonElement jsonElement = gson.toJsonTree(object);
    trimJson(jsonElement);
    return jsonElement;
}

/**
 * We've finally made it to a primitive of some sort.  Should we trim it?
 *
 * @param jsonElement in value
 *
 * @return out value
 */
private boolean shouldTrimElement(JsonElement jsonElement) {
    return jsonElement == null || jsonElement.isJsonNull()
            || (jsonElement.isJsonPrimitive()
                && ((jsonElement.getAsJsonPrimitive().isBoolean() && !jsonElement.getAsBoolean()) // trim false
                    || (jsonElement.getAsJsonPrimitive().isString() // also trim the string "false"
                        && "false".equalsIgnoreCase(jsonElement.getAsString()))));
}

/**
 * trimJson
 *
 * @param jsonElement in value
 */
private void trimJson(JsonElement jsonElement) {
    if (jsonElement == null || jsonElement.isJsonNull() || jsonElement.isJsonPrimitive()) {
        return;
    }

    if (jsonElement.isJsonObject()) {
        List<String> toRemove = new ArrayList<>();
        JsonObject asJsonObject = jsonElement.getAsJsonObject();
        for (Map.Entry<String, JsonElement> jsonElementEntry : asJsonObject.entrySet()) {
            if (jsonElementEntry.getValue().isJsonObject() || jsonElementEntry.getValue().isJsonArray()) {
                trimJson(jsonElementEntry.getValue());
            } else if (shouldTrimElement(jsonElementEntry.getValue())) {
                toRemove.add(jsonElementEntry.getKey());
            }
        }
        if (CollectionUtils.isNotEmpty(toRemove)) {
            for (String remove : toRemove) {
                asJsonObject.remove(remove);
            }
        }
    } else if (jsonElement.isJsonArray()) {
        JsonArray asJsonArray = jsonElement.getAsJsonArray();
        for (JsonElement element : asJsonArray) {
            trimJson(element);
        }
    }
}
}

Upvotes: 0

Related Questions