Я думаю, что вы могли бы делать то, что вам нужно с помощью нескольких аннотаций Джексон:
public abstract class UserDefinedResponse {
@JsonIgnore
public String customString1;
@JsonIgnore
public String customString2;
@JsonIgnore
public String customString3;
@JsonIgnore
public String customString4;
@JsonIgnore // Remove if clientId must be serialized
public String clientId;
private Map<String, Object> dynamicProperties = new HashMap<>();
@JsonAnyGetter
public Map<String, Object> getDynamicProperties() {
Mapper.fillDynamicProperties(this, this.dynamicProperties);
return this.dynamicProperties;
}
@JsonAnySetter
public void setDynamicProperty(String name, Object value) {
this.dynamicProperties.put(name, value);
Mapper.setDynamicProperty(this.dynamicProperties, name, this);
}
}
Во-первых, аннотировать все свойства базового класса с @JsonIgnore
, так как они не будут частью ответ. Затем используйте аннотацию @JsonAnyGetter
, чтобы сгладить карту dynamicProperties
, которая сохранит динамические свойства. Наконец, аннотация для @JsonAnySetter
предназначена для использования Джексоном при десериализации.
Недостающая часть класс Mapper
утилиты:
public abstract class Mapper<T extends UserDefinedResponse> {
private static final Map<Class<T>, Map<String, Mapper<T>>> MAPPERS = new HashMap<>();
static {
// Mappers for Products
Map<String, Mapper<Product>> productMappers = new HashMap<>();
productMappers.put("CLIENT_1", new ProductMapperClient1());
productMappers.put("CLIENT_2", new ProductMapperClient2());
// etc for rest of clients
MAPPERS.put(Product.class, productMappers);
// Mappers for Providers
Map<String, Mapper<Provider>> providerMappers = new HashMap<>();
providerMappers.put("CLIENT_1", new ProviderMapperClient1());
providerMappers.put("CLIENT_2", new ProviderMapperClient2());
// etc for rest of clients
MAPPERS.put(Provider.class, providerMappers);
// etc for rest of entities
// (each entity needs to add specific mappers for every client)
}
protected Mapper() {
}
public static void fillDynamicProperties(T response, Map<String, Object> dynamicProperties) {
// Get mapper for entity and client
Mapper<T> mapper = MAPPERS.get(response.getClass()).get(response.clientId);
// Perform entity -> map mapping
mapper.mapFromEntity(response, dynamicProperties);
}
public static void setDynamicProperty(Map<String, Object> dynamicProperties, String name, T response) {
// Get mapper for entity and client
Mapper<T> mapper = MAPPERS.get(response.getClass()).get(response.clientId);
// Perform map -> entity mapping
mapper.mapToEntity(dynamicProperties, name, response);
}
protected abstract void mapFromEntity(T response, Map<String, Object> dynamicProperties);
protected abstract void mapToEntity(Map<String, Object> dynamicProperties, String name, T response);
}
И для сущности продукта и клиента CLIENT_1:
public class ProductMapperClient1 extends Mapper<Product> {
@Override
protected void mapFromEntity(Product response, Map<String, Object> dynamicProperties) {
// Actual mapping from Product and CLIENT_1 to map
dynamicProperties.put("supplier", response.customString1);
dynamicProperties.put("warehouse", response.customString2);
}
@Override
protected void mapToEntity(Map<String, Object> dynamicProperties, String name, Product response) {
// Actual mapping from map and CLIENT_1 to Product
String property = (String) dynamicProperties.get(name);
if ("supplier".equals(name)) {
response.customString1 = property;
} else if ("warehouse".equals(name)) {
response.customString2 = property;
}
}
}
Идея заключается в том, что есть определенный картограф для каждого (лиц, клиента) пара.Если у вас много сущностей и/или клиентов, вы можете рассмотреть возможность динамического отображения карты карт, возможно, чтения из некоторого файла конфигурации и использования отражения для считывания свойств объекта.
Спасибо Федерико за ответ. Я попробую и вернусь к вам сегодня. – Bashar
Работал как шарм. Решение было в @JsonAnyGetter – Bashar