如何使用Java和Gson中的Builder模式将select类字段序列化为JSON字符串



我创建了一个具有Builder模式的User类,目的是将其序列化为JSON字符串以进行POST。现在,需求发生了变化,我需要能够修补现有记录,更新记录集中的一个或多个字段,而不是所有字段。下面的例子在User类中有5个字段,但想象一下,如果它有30个甚至40个字段,包括int类型。

import com.google.gson.*;
class User 
{
//All final attributes
private final String firstName;
private final String lastName;
private final int age;
private final String phone;
private final String address;

private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}

//All getter, and NO setter to provide immutability
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
public String getPhone() {
return phone;
}
public String getAddress() {
return address;
}

public static class UserBuilder 
{
private String firstName;
private String lastName;
private int age;
private String phone;
private String address;

public UserBuilder() {
}
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder firstName(String firstName) {
this.firstName = firstName;
return this;
}

public UserBuilder lastName(String lastName) {
this.firstName = lastName;
return this;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
//Return the finally consrcuted User object
public User build() {
User user =  new User(this);
return user;
}
}
}
public class TestUserBuild {
public static void main(String[] args) {
// TODO Auto-generated method stub
User user = new User.UserBuilder().
//No last name
//No age
//No phone
//no address
.firstName("Super")
.build();

System.out.println(user); // User: Super, null, 0, null, null

Gson gson = new Gson();

System.out.println(gson.toJson(user)); // {"firstName":"Super","age":0}
}
}

我没有指定年龄,但它在JSON字符串中。我认为构建器模式将有助于创建任意数量的JSON字符串排列,即更新名字和姓氏、只更新名字、只更新年龄、只更新姓氏和电话号码等

构建器模式方法不是解决这个问题的正确方法吗?如果这是一个可接受的解决方案,我如何利用构建器模式将User类序列化为JSON字符串,但只使用我选择的字段?我可以在Gson库中利用一些东西来实现这项任务吗,比如创建一个自定义类型适配器?也许我可以创建一个自定义类型适配器,将所有字段作为输入,检查每个字段是否为NULL,或者Integers是否为0,然后只使用delta构建JSON字符串。

您的"年龄;字段值为0,因为";int";具有默认值。使用";整数";如果希望年龄字段默认为null。

生成器模式的一些优点是不变性(您可以选择只允许生成器在创建时修改类,从类中删除所有setter(,并且它对于实例化具有多个属性的类来说更简洁。

但是您不需要来保持您的Builder模式不变。如果我正确理解您的需求,您可以在对象创建过程中保留生成器模式以实现多功能性,并保留类上的setter,以便能够轻松更新字段。

import com.google.gson.*;
class User {
//Your attributes don't need to be final
private String firstName;
private String lastName;
private int age;
private String phone;
private String address;
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//getters AND setters (omitted for brevity)
//builder class stays as is, omitted for brevity
public class TestUserBuild {
public static void main(String[] args) {
User user = new User.UserBuilder()
.firstName("Super")
.build();

//when you need to update
user.setAge(42);
}
}

问题是,如果你需要定期更新字段,为什么你想要不变性?是否应该完全删除不变性约束(通过在类中保留setter(?您是否需要能够根据特定的业务规则更新特定的字段组合?如果后者是真的,我建议放弃贫血模型("一袋getters和setters"(,并添加负责更新相关字段的特定领域方法。你的User类会是这样的:

class User {
//Your attributes don't need to be final
private String firstName;
private String lastName;
private int age;
private String phone;
private String address;
private User(UserBuilder builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
//getters ONLY (omitted for brevity)
//no setters, only domain-relevant methods which update fields as needed
public void setIdentity(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public void setCoordinates(String phone, String address) {
this.phone = phone;
this.address = address;
}
}
//builder class stays as is
public class TestUserBuild {
public static void main(String[] args) {
User user = new User.UserBuilder()
.firstName("Super")
.build();
//update identity (say, your frontend has an "identity" page with only firstName and lastName on it
user.setIdentity("Chris", "Neve");
//your frontend page allowing user to update coordinates
user.setCoordinates("+331231231", "7th av, NYC");
}
}

最新更新