Reputation: 2570
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
Reputation: 12215
Have a look on gson
s 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 Car
s 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
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