如何使用动态数量的元素构造JSON? [英] How to construct a JSON with dynamic number of elements?

查看:104
本文介绍了如何使用动态数量的元素构造JSON?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to construct a JSON object that looks something like this (see below). One of the tricky parts is that the 'accountInfo' is dynamic in that there will be 0 to many key-value pairs.

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

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

I'm trying to think of the best way to approach this. I was thinking of creating classes to represent the object and then convert it into JSON. For the dynamic key-value pairs I'd use a list to hold them.

所以我有这样的事情:

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)等的值。

Does it make this sense to do it this way? I would use something like Jackson to set the values of the POJO ToJson.setZipCode("123") etc.

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

Or is there a simpler/better way I should do something like this?

推荐答案

这是一些使用 gson 反序列化JSON数据:

Here is some example code that uses gson to deserialize the JSON data:

首先,控制器类:

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());
    }

}

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

Next the data model classes. Here is the top level object:

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:

Finally, here is 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 方法,以便于读取输出。

In order for gson to deserialize successfully the appropriate setter methods must be defined for the class member variables and each class must have a zero argument constructor (which is implied when no constructor is explicitly defined). I also defined the toString methods of each to make it easy to read the output.

请注意合作伙伴类使用私有列表< Map< String,String>> accountInfo; 代表帐户信息数据。由于JSON数组中的每个对象都有一个键和值,因此gson能够将它们解析为 Map 对象。您可以将它们表示为自定义对象,但这不是必需的。

Notice that the Partner class uses a private List<Map<String, String>> accountInfo; to represent the account info data. Since each of the objects in the JSON array has a "key" and "value" gson is able to parse them into Map objects. You could represent them as a custom object, but it's not required.

最后的想法:

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

I'm not sure why you have bonusType represented as an object since it only has one field. You could simply represent that as a single name value pair in the top level object instead: "bonusType":"credit"


这样做是否有意义?

Does it make this sense to do it this way?

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

In most cases yes. Working with classes that represent your data model is generally a good idea when you have complex data structures. The alternative is to use more generic classes and objects to parse the data and that tends to lead to longer, less readable, less maintainable code. Furthermore, data model classes like the ones above can be quickly generated by most modern IDEs. It took me only a few minutes to generate those in Eclipse. You basically only need to define the class member variables and the rest is easily generated, which saves you time.

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

On the other hand most parsers ignore extra fields when deserializing JSON data, which means you will have to update your objects whenever you need a new field. If you represented the data as a Map<String,Object> instead the parser would be able to pull in all fields. This is why it depends on your use case as to which method of parsing is best. If you expect to add new fields to the JSON frequently it might be less maintenance to use a more generic representation of the data. However, if you change the existing structure of the JSON frequently or do not expect much change in the JSON then a custom object approach is likely to be less maintenance.

这篇关于如何使用动态数量的元素构造JSON?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆