如何用动态数量的元素构造一个JSON?

时间:2017-11-22 02:58:35

标签: java json jackson

我需要构建一个类似于此的JSON对象(见下文)。其中一个棘手的部分是' accountInfo'是动态的,因为将有0到多个键值对。

{
  "zipCode": "123",
  "name": "bob",
  "partner": {
    "from": "someCompany",
    "accountNumber": "56789",
    "accountInfo": [
      {
        "key": "a",
        "value": "098"
      },
      {
        "key": "b",
        "value": "765"
      }
    ]
  },
  "bonusType": {
    "code": "credit"
  }
}

我试图想出解决这个问题的最佳方法。我正在考虑创建表示对象的类,然后将其转换为JSON。对于动态键值对,我使用列表来保存它们。

所以我有这样的事情:

public class ToJson{
    private String zipCode;
    private String name;
    private Partner partner;
    private BonusType bonusType;
}

public class Partner{
    private String from;
    private String accountNumber;
    private AccountInfo accountInfo;
}

public class AccountInfo{
    private List<ExtraData> extra_data; 
}

public class ExtraData{
    private String key;
    private String value;
}

public class BonusType{
    private String code;
}

这样做是否有意义?我会使用类似Jackson的东西来设置POJO ToJson.setZipCode("123")等的值。

或者有更简单/更好的方式我应该这样做吗?

2 个答案:

答案 0 :(得分:1)

以下是一些使用gson反序列化JSON数据的示例代码:

首先,控制器类:

package gson;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import com.google.gson.Gson;

public class GsonMain {

    public static void main(String[] args) throws IOException {
        Gson gson = new Gson();
        byte[] jsonBytes = Files.readAllBytes(Paths.get("./src/main/java/gson/jsonData.json"));
        String json = new String(jsonBytes);

        // Deserialization
        ToJson result = gson.fromJson(json, ToJson.class);

        System.out.println("RESULTS: "+result.toString());
    }

}

接下来是数据模型类。这是顶级对象:

package gson;

public class ToJson {
    private String zipCode;
    private String name;
    private Partner partner;
    private BonusType bonusType;

    public String getZipCode() {
        return zipCode;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Partner getPartner() {
        return partner;
    }

    public void setPartner(Partner partner) {
        this.partner = partner;
    }

    public BonusType getBonusType() {
        return bonusType;
    }

    public void setBonusType(BonusType bonusType) {
        this.bonusType = bonusType;
    }

    @Override
    public String toString() {
        return "ToJson [zipCode=" + zipCode + ", name=" + name + ", partner=" + partner + ", bonusType=" + bonusType
                + "]";
    }
}

这是合作伙伴:

package gson;

import java.util.List;
import java.util.Map;

public class Partner {
    private String from;
    private String accountNumber;
    private List<Map<String, String>> accountInfo;

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getAccountNumber() {
        return accountNumber;
    }

    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }

    public List<Map<String, String>> getAccountInfo() {
        return accountInfo;
    }

    public void setAccountInfo(List<Map<String, String>> accountInfo) {
        this.accountInfo = accountInfo;
    }

    @Override
    public String toString() {
        return "Partner [from=" + from + ", accountNumber=" + accountNumber + ", accountInfo=" + accountInfo + "]";
    }
}

最后,这是BonusType:

package gson;

public class BonusType {
    private String code;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Override
    public String toString() {
        return "BonusType [code=" + code + "]";
    }
}

为了使gson成功反序列化,必须为类成员变量定义适当的setter方法,并且每个类必须具有零参数构造函数(在没有显式定义构造函数时隐含)。我还定义了每个toString方法,以便于读取输出。

请注意,Partner类使用private List<Map<String, String>> accountInfo;来表示帐户信息数据。由于JSON数组中的每个对象都有一个&#34;键&#34;和&#34;价值&#34; gson能够将它们解析为Map个对象。您可以将它们表示为自定义对象,但不是必需的。

最后的一些想法:

我不确定为什么你将bonusType表示为一个对象,因为它只有一个字段。您可以简单地将其表示为顶级对象中的单个名称值对:"bonusType":"credit"

  

这样做是否有意义?

在大多数情况下是的。当您拥有复杂的数据结构时,使用代表您的数据模型的类通常是个好主意。另一种方法是使用更通用的类和对象来解析数据,这往往会导致代码更长,可读性更低,维护更少。此外,大多数现代IDE都可以快速生成上述数据模型类。我花了几分钟才在Eclipse中生成它们。您基本上只需要定义类成员变量,其余的很容易生成,这样可以节省您的时间。

另一方面,大多数解析器在反序列化JSON数据时会忽略额外的字段,这意味着您需要在需要新字段时更新对象。如果您将数据表示为Map<String,Object>,则解析器将能够拉入所有字段。这就是为什么它取决于您的用例,哪种解析方法最好。如果您希望经常向JSON添加新字段,那么使用更通用的数据表示可能会减少维护。但是,如果您经常更改JSON的现有结构,或者不希望在JSON中进行太多更改,那么自定义对象方法可能会减少维护。

答案 1 :(得分:0)

[       {         &#34; key&#34;:&#34; a&#34;,         &#34;价值&#34;:&#34; 098&#34;       },       {         &#34; key&#34;:&#34; b&#34;,         &#34;价值&#34;:&#34; 765&#34;       } ]

是ExtraData类的列表 所以Partner类应该是这样的。

public class Partner {
    private String from;
    private String accountNumber;
    private ArrayList<ExtraData> accountInfo;
}