I am creating JSON mapper that will create JSON schema for my JPA database classes. I am using mbknor-jackson-jsonSchema that works great, but I need to serialize my subclasses as id only. so far my structure is:
public class ModelPojo{
private List<Table> table;
private List<Table2> table2;
}
both table classes are smth like this:
@Table(name = "TABLE")
public class Table extends BaseEntity {
@Column(name = "SMTH")
private String smth;
@JoinColumn(name = "TABLE2")
private Table2 table2; //now this is where is the problem
}
Base entity contains id
the question is, is there a way to write custom std serializer that serialize table entity to have property id_table2: "integer" not the whole object?
I tried to override serialize method for StdSerializer<BaseEntity>
which does not work, it is not called when creating the schema
Edit: I now get
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Model Pojo",
"type": "object",
"additionalProperties": false,
"properties": {
"Table": {
"type": "array",
"items": {
"$ref": "#/definitions/Table"
}
}
"Table2": {
"type": "array",
"items": {
"$ref": "#/definitions/Table2"
}
}
},
"definitions": {
"Table": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "integer"
},
"table2": {
"$ref": "#/definitions/Table2"
},
"smth": {
"type": "string"
}
}
},
"Table2": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "integer"
},
"foo": {
"type": "string"
}
}
}
}
}
and i want to change
"table2": {
"$ref": "#/definitions/Table2"
},
to
"table2_id": {
"type": "integer"
},
the structure of joined tables is much more complex so I am trying to not manualy add @JsonIgnore and changing it manually, but write some type of serializer that retypes the child instances of BaseEntity to id, hope its understandable
CodePudding user response:
If you want to ignore all properties of your domain entities Table
and Table2
apart from id
(inherited from BaseEntity
) while serializing ModelPojo
but at the same to be able to reflect all the properties Table
and Table2
while serializing them as standalone objects, you can introduce a method inside ModelPojo
which to instruct the Jackson how to dial with this class.
public class ModelPojo {
private List<Table> table;
private List<Table2> table2;
public List<Map<String, Integer>> getTable() {
return extractIds(table);
}
public List<Map<String, Integer>> getTable2() {
return extractIds(table2);
}
private List<Map<String, Integer>> extractIds(List<? extends BaseEntity> list) {
return list.stream().map(t -> Map.of("id", t.getId())).toList();
}
}
In the absence of real getters, getTable()
and getTable2()
would be used by Jackson. No data-binding annotations required.
But you might need normal getters, that's understandable.
In such case, the approach described above can be improved by introducing a single method returning a Map
(as a replacement of getTable()
and getTable2()
) annotated with @JsonAnyGetter
(to make Jackson aware of this method) and @JsonUnwrapped
(to flatten the contents of this map).
The fields table
and table2
should be annotated with @JsonIgnore
.
public class ModelPojo {
@JsonIgnore
private List<Table> table;
@JsonIgnore
private List<Table2> table2;
@JsonAnyGetter
@JsonUnwrapped
public Map<String, List<Map<String, Integer>>> getAll() {
return Map.of(
"table", extractIds(table),
"table2", List.of()
);
}
private List<Map<String, Integer>> extractIds(List<? extends BaseEntity> list) {
return list.stream().map(t -> Map.of("id", t.getId())).toList();
}
// getters
}
I am trying to not manualy add
@JsonIgnore
and changing it manually, but write some type of serializer that retypes the child instances ofBaseEntity
toid
Sure, you can implement a custom serializer for these fields as well.
For that, you need extend JsonSerializer
class and implement its abstract
method serialize()
.
public class TableSerializer extends JsonSerializer<List<? extends BaseEntity>> {
@Override
public void serialize(List<? extends BaseEntity> list,
JsonGenerator gen,
SerializerProvider serializers)
throws IOException {
gen.writeObject(extractIds(list));
}
private List<Map<String, Integer>> extractIds(List<? extends BaseEntity> list) {
return list.stream().map(t -> Map.of("id", t.getId())).toList();
}
}
public class ModelPojo {
@JsonSerialize(using = TableSerializer.class)
private List<Table> table;
@JsonSerialize(using = TableSerializer.class)
private List<Table2> table2;
// getters
}
CodePudding user response:
In table2 you can write @JsonIgnore
on the top field which you do not want to serialize it will not send it in json response. You can do it for all other fields than id