如何使用java和gson中的构建器模式将select类字段序列化为json字符串?

alen0pnh  于 2021-08-20  发布在  Java
关注(0)|答案(1)|浏览(394)

我创建了一个带有生成器模式的用户类,目的是将其序列化为一个json字符串,以便发布。现在,需求已经改变,我需要能够修补现有记录,更新记录集中的一个或多个字段,但不是所有字段。下面的示例在其用户类中有5个字段,但是想象一下,如果它有30个甚至40个字段,包括int类型。

  1. import com.google.gson.*;
  2. class User
  3. {
  4. //All final attributes
  5. private final String firstName;
  6. private final String lastName;
  7. private final int age;
  8. private final String phone;
  9. private final String address;
  10. private User(UserBuilder builder) {
  11. this.firstName = builder.firstName;
  12. this.lastName = builder.lastName;
  13. this.age = builder.age;
  14. this.phone = builder.phone;
  15. this.address = builder.address;
  16. }
  17. //All getter, and NO setter to provide immutability
  18. public String getFirstName() {
  19. return firstName;
  20. }
  21. public String getLastName() {
  22. return lastName;
  23. }
  24. public int getAge() {
  25. return age;
  26. }
  27. public String getPhone() {
  28. return phone;
  29. }
  30. public String getAddress() {
  31. return address;
  32. }
  33. public static class UserBuilder
  34. {
  35. private String firstName;
  36. private String lastName;
  37. private int age;
  38. private String phone;
  39. private String address;
  40. public UserBuilder() {
  41. }
  42. public UserBuilder(String firstName, String lastName) {
  43. this.firstName = firstName;
  44. this.lastName = lastName;
  45. }
  46. public UserBuilder firstName(String firstName) {
  47. this.firstName = firstName;
  48. return this;
  49. }
  50. public UserBuilder lastName(String lastName) {
  51. this.firstName = lastName;
  52. return this;
  53. }
  54. public UserBuilder age(int age) {
  55. this.age = age;
  56. return this;
  57. }
  58. public UserBuilder phone(String phone) {
  59. this.phone = phone;
  60. return this;
  61. }
  62. public UserBuilder address(String address) {
  63. this.address = address;
  64. return this;
  65. }
  66. //Return the finally consrcuted User object
  67. public User build() {
  68. User user = new User(this);
  69. return user;
  70. }
  71. }
  72. }
  73. public class TestUserBuild {
  74. public static void main(String[] args) {
  75. // TODO Auto-generated method stub
  76. User user = new User.UserBuilder().
  77. //No last name
  78. //No age
  79. //No phone
  80. //no address
  81. .firstName("Super")
  82. .build();
  83. System.out.println(user); // User: Super, null, 0, null, null
  84. Gson gson = new Gson();
  85. System.out.println(gson.toJson(user)); // {"firstName":"Super","age":0}
  86. }
  87. }

我没有指定年龄,但它在json字符串中。我认为构建器模式将有助于创建任意数量的json字符串排列,即更新名字和姓氏、仅更新名字、仅更新年龄、仅更新姓氏和电话号码等。。。
对于这个问题,生成器模式方法不是正确的解决方案吗?如果这是一个可接受的解决方案,我如何利用构建器模式将用户类序列化为json字符串,但只使用我选择的字段?在gson库中是否有我可以利用的东西来实现这个任务,比如创建自定义类型适配器?也许我可以创建一个自定义类型适配器,它将所有字段作为输入,检查每个字段是否为null,或者是否为0表示整数,然后只使用delta构建json字符串。

7kjnsjlb

7kjnsjlb1#

您的“年龄”字段值为0,因为“int”有一个默认值。如果希望年龄字段默认为空,请使用“整数”。
构建器模式的一些优点是不可变的(您可以选择只允许构建器在创建时修改类,从类中删除所有setter),并且对于示例化具有多个属性的类更简洁。
但您不需要保持构建器模式不变。如果我正确理解您的需求,您可以在对象创建过程中保持生成器模式的多功能性,并保持类上的setter能够轻松地更新字段。

  1. import com.google.gson.*;
  2. class User {
  3. //Your attributes don't need to be final
  4. private String firstName;
  5. private String lastName;
  6. private int age;
  7. private String phone;
  8. private String address;
  9. private User(UserBuilder builder) {
  10. this.firstName = builder.firstName;
  11. this.lastName = builder.lastName;
  12. this.age = builder.age;
  13. this.phone = builder.phone;
  14. this.address = builder.address;
  15. }
  16. //getters AND setters (omitted for brevity)
  17. //builder class stays as is, omitted for brevity
  18. public class TestUserBuild {
  19. public static void main(String[] args) {
  20. User user = new User.UserBuilder()
  21. .firstName("Super")
  22. .build();
  23. //when you need to update
  24. user.setAge(42);
  25. }
  26. }

问题是,如果需要定期更新字段,为什么需要不变性?您是否应该完全删除不变性约束(通过在类中保留setter)?您是否需要能够根据特定的业务规则更新特定的字段组合?如果后者是真的,我建议不要使用贫血模型(一个“getter和setter包”),而是添加特定于领域的方法来更新相关字段。您的用户类将如下所示:

  1. class User {
  2. //Your attributes don't need to be final
  3. private String firstName;
  4. private String lastName;
  5. private int age;
  6. private String phone;
  7. private String address;
  8. private User(UserBuilder builder) {
  9. this.firstName = builder.firstName;
  10. this.lastName = builder.lastName;
  11. this.age = builder.age;
  12. this.phone = builder.phone;
  13. this.address = builder.address;
  14. }
  15. //getters ONLY (omitted for brevity)
  16. //no setters, only domain-relevant methods which update fields as needed
  17. public void setIdentity(String firstName, String lastName) {
  18. this.firstName = firstName;
  19. this.lastName = lastName;
  20. }
  21. public void setCoordinates(String phone, String address) {
  22. this.phone = phone;
  23. this.address = address;
  24. }
  25. }
  26. //builder class stays as is
  27. public class TestUserBuild {
  28. public static void main(String[] args) {
  29. User user = new User.UserBuilder()
  30. .firstName("Super")
  31. .build();
  32. //update identity (say, your frontend has an "identity" page with only firstName and lastName on it
  33. user.setIdentity("Chris", "Neve");
  34. //your frontend page allowing user to update coordinates
  35. user.setCoordinates("+331231231", "7th av, NYC");
  36. }
  37. }
展开查看全部

相关问题