【问题标题】:How to serialize json to another json by preserving data types of key?如何通过保留键的数据类型将 json 序列化为另一个 json?
【发布时间】:2015-02-04 09:51:06
【问题描述】:

我有这样的原始 JSON 字符串,其中我有如下所示的键和值 -

{
  "u":{
     "string":"1235"
  },
  "p":"2047935",
  "client_id":{
     "string":"5"
  },
  "origin":null,
  "item_condition":null,
  "country_id":{
     "int":3
  },
  "timestamp":{
     "long":1417823759555
  },
  "impression_id":{
     "string":"2345HH*"
  },
  "is_consumerid":true,
  "is_pid":false
}

例如,一个键是"u",它的值是-

{
    "string":"1235"
}

同样的另一个键是"country_id",它的值是-

{
    "int":3
}

现在我需要做的是,我需要表示键值对,如下所示。如果任何值是字符串数据类型(如键 u 的值),则用双引号表示它的值,否则不要用双引号表示它的值。 country_id 的含义值不会在字符串双引号中,因为它是一个 int。

"u": "1235"
"p": "2047935"
"client_id": "5"
"origin":null
"item_condition":null
"country_id": 3 // I don't have double quotes here around 3 since country_id was int that's why
"timestamp": 1417823759555
"impression_id": "2345HH*"
"is_consumerid": true
"is_pid": false

然后我需要制作另一个看起来像这样的 json 字符串 -

{
    "u": "1235",
    "p": "2047935",
    "client_id": "5",
    "origin":null,
    "item_condition":null,
    "country_id": 3,
    "timestamp": 1417823759555,
    "impression_id": "2345HH*",
    "is_consumerid": true,
    "is_pid": false
}

所以我从下面的代码开始,但无法理解我应该进一步做什么?

    String response = "original_json_string";
    Type type = new TypeToken<Map<String, Object>>() {}.getType();

    JsonObject jsonObject = new JsonParser().parse(response).getAsJsonObject();

    for (Map.Entry<String, JsonElement> object : jsonObject.entrySet()) {
        if (object.getValue() instanceof JsonObject) {
            String data = object.getValue().toString();
            // now not sure what should I do here?

        }
    }

我的新 json 在序列化后应该像这样打印出来。

{
    "u": "1235",
    "p": "2047935",
    "client_id": "5",
    "origin":null,
    "item_condition":null,
    "country_id": 3,
    "timestamp": 1417823759555,
    "impression_id": "2345HH*",
    "is_consumerid": true,
    "is_pid": false
}

实现这一目标的最佳方法是什么?

【问题讨论】:

  • 能否请您告诉我 JSON 的原始结构是否已修复。我的意思是每次“client_id”都会有“string”或者它也可以有“long”?
  • @ShaikhMohammedShariq 是的,它已修复。简而言之,如果任何键是字符串,它们将始终是字符串。 int、long、boolean 也是如此。

标签: java json string serialization gson


【解决方案1】:

请注意,我对 Gson 的经验还不是很丰富,因此可能有最简单的方法。在我们之前的讨论之后,这个解决方案也出现了。

基本上,问题是在 json 文件中取回所需的类型(由 addEntry 方法完成)并且每个 @event 键都应该有自己的 JSON 字符串(由 computeJson 完成)。由于只有两个嵌套级别,因此可以这样做。否则,递归方法就可以解决问题。

因此,如果您只有一个嵌套级别,则应该迭代其他 JsonObject 的条目。对于每个条目,computeJson 将在 List 中添加一个新的 Json 条目,该条目对应于每个 @event 键。

public class Test {
    public static void main(String[] args) throws Exception {   
        List<String> output = new ArrayList<>();
        JsonObject jsonObject = new JsonParser().parse(new FileReader("myJson.json")).getAsJsonObject();
        for (Map.Entry<String, JsonElement> object : jsonObject.entrySet()) {
            if (object.getValue() instanceof JsonObject) {
                output.add(computeJson((JsonObject)object.getValue()));
            }
        }
        System.out.println(output);
    }

    private static String computeJson(JsonObject source) {
        JsonObject output = new JsonObject();
        for (Map.Entry<String, JsonElement> object : source.entrySet()) {
            if (object.getValue() instanceof JsonObject) {
                for(Map.Entry<String, JsonElement> entry : ((JsonObject)object.getValue()).entrySet()) {
                    addEntry(object.getKey(), output, entry);
                }
            } else {
                addEntry(object.getKey(), output, object);
            }
        }
        Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
        return gson.toJson(output);
    }

    private static void addEntry(String key, JsonObject output, Map.Entry<String, JsonElement> object) {
        switch(object.getKey().toLowerCase()) {
            case "string":
                output.addProperty(key, object.getValue().getAsString());
                break;
            case "int":
                output.addProperty(key, object.getValue().getAsInt());
                break;
            case "long":
                output.addProperty(key, object.getValue().getAsLong());
                break;
            //add other primitive cases
            default:
                output.add(key, object.getValue());
        }
    }
}

【讨论】:

  • 这比我在下面发布的解决方案要简洁得多。 +1
  • 它就像一个魅力。非常感谢您的帮助。我将使用各种 Json 对其进行更多测试。
【解决方案2】:

RawCollectionsExample 所述,您可以手动解析 json 并将其设置在所需的对象中。解析并设置值后,您可以再次序列化 java 对象以获得所需的 json。

要从您的 json 设置值,您需要有如下所示的 POJO。

public class CustomObject {

    private String u;
    private String p;
    private String client_id;
    private String origin;
    private String item_condition;
    private int country_id;
    private long timestamp;
    private String impression_id;
    private boolean is_consumerid;
    private boolean is_pid;
    public String getU() {
        return u;
    }
    public void setU(String u) {
        this.u = u;
    }
    public String getP() {
        return p;
    }
    public void setP(String p) {
        this.p = p;
    }
    public String getClient_id() {
        return client_id;
    }
    public void setClient_id(String clientId) {
        client_id = clientId;
    }
    public String getOrigin() {
        return origin;
    }
    public void setOrigin(String origin) {
        this.origin = origin;
    }
    public String getItem_condition() {
        return item_condition;
    }
    public void setItem_condition(String itemCondition) {
        item_condition = itemCondition;
    }
    public int getCountry_id() {
        return country_id;
    }
    public void setCountry_id(int countryId) {
        country_id = countryId;
    }
    public long getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }
    public String getImpression_id() {
        return impression_id;
    }
    public void setImpression_id(String impressionId) {
        impression_id = impressionId;
    }
    public boolean isIs_consumerid() {
        return is_consumerid;
    }
    public void setIs_consumerid(boolean isConsumerid) {
        is_consumerid = isConsumerid;
    }
    public boolean isIs_pid() {
        return is_pid;
    }
    public void setIs_pid(boolean isPid) {
        is_pid = isPid;
    }
    @Override
    public String toString() {
        return "CustomObject [client_id=" + client_id + ", country_id="
                + country_id + ", impression_id=" + impression_id
                + ", is_consumerid=" + is_consumerid + ", is_pid=" + is_pid
                + ", item_condition=" + item_condition + ", origin=" + origin
                + ", p=" + p + ", timestamp=" + timestamp + ", u=" + u + "]";
    }

}

在上面的 POJO 中,您可以手动解析和设置 JSON 值,如下所示:

String jsonLine = "{  \"u\":{     \"string\":\"1235\"  },  \"p\":\"2047935\",  \"client_id\":{     \"string\":\"5\"  },  \"origin\":null,  \"item_condition\":null,  \"country_id\":{     \"int\":3  },  \"timestamp\":{     \"long\":1417823759555  },  \"impression_id\":{     \"string\":\"2345HH*\"  },  \"is_consumerid\":true,  \"is_pid\":false}";
JsonParser parser = new JsonParser();

//in case you have json array you need to use .getAsJsonArray instead of getAsJsonObject
JsonObject jsonObject = parser.parse(jsonLine).getAsJsonObject();
CustomObject obj = new CustomObject();

obj.setP(jsonObject.get("p").getAsString());
obj.setU(jsonObject.get("u").getAsJsonObject().get("string").getAsString());
obj.setClient_id(jsonObject.get("client_id").getAsJsonObject().get("string").getAsString());

//null check which will be required for each value in case there are possibility of having null values
String origin = jsonObject.get("origin").isJsonNull() ==true?null:jsonObject.get("origin").getAsString();
obj.setOrigin(origin);
String itemCondition = jsonObject.get("item_condition").isJsonNull() ==true?null:jsonObject.get("item_condition").getAsString();
obj.setItem_condition(itemCondition);
obj.setCountry_id(jsonObject.get("country_id").getAsJsonObject().get("int").getAsInt());
obj.setTimestamp(jsonObject.get("timestamp").getAsJsonObject().get("long").getAsLong());
obj.setImpression_id(jsonObject.get("impression_id").getAsJsonObject().get("string").getAsString());
obj.setIs_consumerid(jsonObject.get("is_consumerid").getAsBoolean());
obj.setIs_pid(jsonObject.get("is_consumerid").getAsBoolean());
System.out.println("JSON OUTPUT "+ new Gson().toJson(obj));

您可以在任何类的 main 方法中运行代码 sn-p 进行验证。检查上面输出所需 json 的最后一行。如果这不是您想要的,请告诉我。

【讨论】:

    猜你喜欢
    • 2018-05-21
    • 2021-12-28
    • 1970-01-01
    • 2015-08-31
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多