kkflf
kkflf

Reputation: 2570

In JSON serialization howto ignore some of Class1 field(s) in case Class1 is a field of Class2?

I searched for this question on stackoverflow and google and I couldn't find any proper answer.

How do I ignore fields from an object within an object?

I think it will be much easier to understand with an example:

(Editors note, in title: Class1=Engine a field for Class2=Car)

class Car {
    Integer id;
    Integer numberOfWheels;
    Engine engine;
}   

class Engine {
    Integer id;
    String name;
    String producer;
    Integer horsePower;
    Integer weight; 
}

The Car JSON should consist of all fields, but the Engine object within the Car object should be limited to id, name, producer.

{
  "id":1,
  "numberOfWheels":4,
  "engine": {
    "id":1,
    "name":"some engine"
    "producer":"some engine producer"
  }
}

The Engine JSON should however consist of all fields id, name, producer, horsePower, weight

{
    "id":1,
    "name":"some engine"
    "producer":"some engine producer"
    "horsePower":250
    "weight":500
}

Just to clarify. The fields horsePower and weight should only be ignored in the JSON generated from Car.

Upvotes: 1

Views: 309

Answers (2)

pirho
pirho

Reputation: 12215

Have a look on gsons JsonSerializer and ExclusionStrategy. Maybe not the most terse way to do it - especially compared to your own solution - but a good option in general.

To enable Car to have some special treatment create JsonSerializer like

public class CarSerializer implements JsonSerializer<Car> {
    private final Gson gson = new GsonBuilder()
            .addSerializationExclusionStrategy(new FieldExclusionStrategy()).create();

    @Override
    public JsonElement serialize(Car arg0, Type arg1, JsonSerializationContext arg2) {
        return new JsonParser().parse(gson.toJson(arg0));
    }
}

Above has its own gson to handle only Car and not to mess any other serialization. Beforementioned registers ExclusionStrategy to its own private use that checks that if Cars field is Engine then any unwanted field in Engine is skipped.

public class FieldExclusionStrategy  implements ExclusionStrategy {
    private Set<String> ignored = 
            new HashSet<String>(Arrays.asList( new String[]{"horsePower","weight"}));
    @Override
    public boolean shouldSkipField(FieldAttributes arg0) {
        if(arg0.getDeclaringClass().isAssignableFrom(Engine.class))
            if(ignored.contains(arg0.getName())) return true;
        return false;
    }       
    @Override
    public boolean shouldSkipClass(Class<?> arg0) { return false; }
}

And it can be used with gson that registers JsonSerializer as its type adapter for Car.class:

Gson gson = new GsonBuilder().setPrettyPrinting()
      .registerTypeAdapter(Car.class, new CarSerializer()).create();

Upvotes: 1

kkflf
kkflf

Reputation: 2570

I got impatience and decided to create a temporary solution until I find a better way. This solution may or may not be best practice, but I do not have any better solution.

I have decided to post my temporary solution if anyone ever finds this question and wonder about a solution.

I am still looking for a typesafe and best practice solution, so if anyone got any answers please post it. I will accept your answer regardless of when you post your solution.

class Car {
    Integer id;
    Integer numberOfWheels;
    @JsonIgnore
    Engine engine;

    @JsonProperty("engine")
    public Map<String, Object> getEngineFormatted(){
        return engine == null ? null : engine.getFormatted();
    }
}   

class Engine {
    Integer id;
    String name;
    String producer;
    Integer horsePower;
    Integer weight; 

    public Map<String, Object> getFormatted(){
        Map<String, Object> map = new HashMap<>();

        map.put("id", id);
        map.put("name", name);
        map.put("producer", producer);

        return map;
    }
}

Car JSON:

{
  "id":1,
  "numberOfWheels":4,
  "engine": {
    "id":1,
    "name":"some engine"
    "producer":"some engine producer"
  }
}

Engine JSON

{
    "id":1,
    "name":"some engine"
    "producer":"some engine producer"
    "horsePower":250
    "weight":500
}

Upvotes: 0

Related Questions