序列化逻辑应该在实体中还是其他class
Should serialization logic be in the entity or other class
对象序列化逻辑(将字段映射到 XML 或 JSON 名称和值)应该放在哪里?在每个实体对象内部或进入一组不同的 classes 只关心序列化?还有其他与此问题相关的最佳实践吗?
例如:
class Person {
String name;
}
有些人是这样处理的:
class Person {
String name;
public String toJson () {
// build JSON, use 'name' field
}
}
但是如果我们还需要 XML()、toCSV()、toXYZ() 保持这个方向会产生可怕的污染代码并破坏单一责任原则,即使使用单个 toJson 方法也已经被破坏, 恕我直言。
另一种选择,这是我通常做的:
interface Serializer { public String toJson (); }
class PersonJsonSerializer implements Serializer {
private Person p;
public PersonJsonSerializer (Person p) { this.person = p; }
public String toJson () {
// build JSON, use p.name
}
}
然后工厂根据实体类型分发序列化程序:
class JsonSerializerFactory {
public Serializer getSerializer (Object o) {
if (o instanceof Person) {
return new PersonJsonSerializer ((Person)o);
}
else if (o instanceof Account) {
return new AccountJsonSerializer ((Account)o);
}
// ... etc
}
}
还有 XMLSerializerFactory、CSVSerializerFactory 等等。
然而,大多数时候人们希望完全控制序列化,不会接受它,而更喜欢在每个 class 中使用 toJson 方法。他们会声称更简单,更不容易出错。
首选的方法是什么?是否有更好的替代方案来解决这个问题?
我会说序列化逻辑不应该是 POCO/data classes 的一部分,原因有很多:
- 单一职责原则(数据classes应该只定义数据模型,注意序列化逻辑)
- 您可能需要不同类型的序列化器(json/xml 等等,如您所述)
- 序列化实现大部分时间是通用解决方案或外部包。即使你想为某些对象自定义实现,你仍然可以有一个通用的解决方案,你可以为特定的 classes 扩展,所以不需要为每个 class.
都拥有它
- 您可以使用属性装饰您的 POCO classes 以针对特殊条件引导序列化程序(例如控制属性序列、属性 名称,甚至是复杂类型属性的客户序列化程序)
还有其他原因,但有一些强有力的论据表明您不应该将序列化逻辑放入您的 POCO/Data 模型中。
自定义JSON使用序列化的对象非常简单。
我在我的项目中写了一个 claas,我给你一个线索,告诉你如何在项目中实现它
Application (POJO Class)
import java.io.Serializable;
import java.util.List;
import org.webservice.business.serializer.ApplicationSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@JsonSerialize(using=ApplicationSerializer.class)
public class Application implements Serializable {
private static final long serialVersionUID = 1L;
private double amount;
private String businessType;
private String currency;
private int duration;
}
Now LoanApplicationSerializer class that contains the Customization
using Serialization Logic................
package org.webservice.business.serializer;
import java.io.IOException;
import org.webservice.business.dto.Application;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class ApplicationSerializer extends JsonSerializer<Application> {
@Override
public void serialize(Application prm_objObjectToSerialize, JsonGenerator prm_objJsonGenerator, SerializerProvider prm_objSerializerProvider) throws IOException, JsonProcessingException {
if (null == prm_objObjectToSerialize) {
} else {
try {
prm_objJsonGenerator.writeStartObject();
prm_objJsonGenerator.writeNumberField("amount", prm_objObjectToSerialize.getAmount());
prm_objJsonGenerator.writeNumberField("duration", prm_objObjectToSerialize.getDuration());
prm_objJsonGenerator.writeStringField("businesstype", prm_objObjectToSerialize.getBusinessType());
prm_objJsonGenerator.writeStringField("currency", prm_objObjectToSerialize.getCurrency());
} catch (Exception v_exException) {
v_exException.printStackTrace()
} finally {
prm_objJsonGenerator.writeEndObject();
}
}
}
对象序列化逻辑(将字段映射到 XML 或 JSON 名称和值)应该放在哪里?在每个实体对象内部或进入一组不同的 classes 只关心序列化?还有其他与此问题相关的最佳实践吗?
例如:
class Person {
String name;
}
有些人是这样处理的:
class Person {
String name;
public String toJson () {
// build JSON, use 'name' field
}
}
但是如果我们还需要 XML()、toCSV()、toXYZ() 保持这个方向会产生可怕的污染代码并破坏单一责任原则,即使使用单个 toJson 方法也已经被破坏, 恕我直言。
另一种选择,这是我通常做的:
interface Serializer { public String toJson (); }
class PersonJsonSerializer implements Serializer {
private Person p;
public PersonJsonSerializer (Person p) { this.person = p; }
public String toJson () {
// build JSON, use p.name
}
}
然后工厂根据实体类型分发序列化程序:
class JsonSerializerFactory {
public Serializer getSerializer (Object o) {
if (o instanceof Person) {
return new PersonJsonSerializer ((Person)o);
}
else if (o instanceof Account) {
return new AccountJsonSerializer ((Account)o);
}
// ... etc
}
}
还有 XMLSerializerFactory、CSVSerializerFactory 等等。
然而,大多数时候人们希望完全控制序列化,不会接受它,而更喜欢在每个 class 中使用 toJson 方法。他们会声称更简单,更不容易出错。
首选的方法是什么?是否有更好的替代方案来解决这个问题?
我会说序列化逻辑不应该是 POCO/data classes 的一部分,原因有很多:
- 单一职责原则(数据classes应该只定义数据模型,注意序列化逻辑)
- 您可能需要不同类型的序列化器(json/xml 等等,如您所述)
- 序列化实现大部分时间是通用解决方案或外部包。即使你想为某些对象自定义实现,你仍然可以有一个通用的解决方案,你可以为特定的 classes 扩展,所以不需要为每个 class. 都拥有它
- 您可以使用属性装饰您的 POCO classes 以针对特殊条件引导序列化程序(例如控制属性序列、属性 名称,甚至是复杂类型属性的客户序列化程序)
还有其他原因,但有一些强有力的论据表明您不应该将序列化逻辑放入您的 POCO/Data 模型中。
自定义JSON使用序列化的对象非常简单。
我在我的项目中写了一个 claas,我给你一个线索,告诉你如何在项目中实现它
Application (POJO Class)
import java.io.Serializable;
import java.util.List;
import org.webservice.business.serializer.ApplicationSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@JsonSerialize(using=ApplicationSerializer.class)
public class Application implements Serializable {
private static final long serialVersionUID = 1L;
private double amount;
private String businessType;
private String currency;
private int duration;
}
Now LoanApplicationSerializer class that contains the Customization using Serialization Logic................
package org.webservice.business.serializer;
import java.io.IOException;
import org.webservice.business.dto.Application;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class ApplicationSerializer extends JsonSerializer<Application> {
@Override
public void serialize(Application prm_objObjectToSerialize, JsonGenerator prm_objJsonGenerator, SerializerProvider prm_objSerializerProvider) throws IOException, JsonProcessingException {
if (null == prm_objObjectToSerialize) {
} else {
try {
prm_objJsonGenerator.writeStartObject();
prm_objJsonGenerator.writeNumberField("amount", prm_objObjectToSerialize.getAmount());
prm_objJsonGenerator.writeNumberField("duration", prm_objObjectToSerialize.getDuration());
prm_objJsonGenerator.writeStringField("businesstype", prm_objObjectToSerialize.getBusinessType());
prm_objJsonGenerator.writeStringField("currency", prm_objObjectToSerialize.getCurrency());
} catch (Exception v_exException) {
v_exException.printStackTrace()
} finally {
prm_objJsonGenerator.writeEndObject();
}
}
}