序列化逻辑应该在实体还是其他类中

Jos*_*tes 5 java serialization json design-patterns pojo

对象序列化逻辑(字段到 XML 或 JSON 名称和值的映射)应该放在哪里?在每个实体对象内部或进入一组仅与序列化有关的不同类?与此问题相关的任何其他最佳实践?

例如:

class Person {
    String name;
}
Run Code Online (Sandbox Code Playgroud)

有些人是这样处理的:

class Person {
    String name;
    public String toJson () {
      // build JSON, use 'name' field
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我们还需要 toXML()、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
    }
}
Run Code Online (Sandbox Code Playgroud)

然后工厂根据实体类型分发序列化程序:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

还有 XMLSerializerFactory、CSVSerializerFactory 等等。

然而,大多数时候人们想要完全控制序列化并且不会购买它并且更喜欢在每个类中都有 toJson 方法。他们会声称更简单,更不容易出错。

首选的方法是什么,是否有更好的替代方案来解决这个问题?

小智 6

我会说序列化逻辑不应该是 POCO/data 类的一部分,原因有很多:

  1. 单一职责原则(数据类应该只定义数据模型,注意序列化逻辑)
  2. 您可能需要不同类型的序列化程序(如您提到的 json/xml 等)
  3. 大多数时候序列化实现是通用解决方案或外部包。即使您想要为某些对象自定义实现,您仍然可以拥有一个通用解决方案,您可以为特定类扩展该解决方案,因此无需为每个类都拥有它。
  4. 您可以使用属性装饰您的 POCO 类,以针对特殊条件引导序列化程序(例如控制属性序列、属性名称,甚至是复杂类型属性的客户序列化程序)

还有其他原因,但有一些强有力的论据为什么不应该将序列化逻辑放入 POCO/数据模型中。