簡體   English   中英

如何在 Gson 序列化中保持字段順序

[英]How to keep fields sequence in Gson serialization

似乎Gson.toJson(Object object)生成具有隨機分布的對象字段的 JSON 代碼。 有沒有辦法以某種方式修復字段順序?

public class Foo {
    public String bar;
    public String baz;
    public Foo( String bar, String baz ) {
        this.bar = bar;
        this.baz = baz;
    }
}
Gson gson = new Gson();
String jsonRequest = gson.toJson(new Foo("bar","baz"));

字符串 jsonRequest 可以是:

  • { "bar":"bar", "baz":"baz" } (正確)
  • { "baz":"baz", "bar":"bar" } (順序錯誤)

您需要創建一個自定義 JSON 序列化程序。

例如

public class FooJsonSerializer implements JsonSerializer<Foo> {

    @Override
    public JsonElement serialize(Foo foo, Type type, JsonSerializationContext context) {
        JsonObject object = new JsonObject();
        object.add("bar", context.serialize(foo.getBar());
        object.add("baz", context.serialize(foo.getBaz());
        // ...
        return object;
    }

}

並按如下方式使用它:

Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class, new FooJsonSerializer()).create();
String json = gson.toJson(foo);
// ...

這會保持您在序列化程序中指定的順序。

也可以看看:

如果 GSON 不支持字段順序的定義,那么還有其他庫支持。 例如, Jackson允許使用 @JsonPropertyOrder 定義它。 必須指定自己的自定義序列化程序對我來說似乎是一項艱巨的工作。

是的,我同意根據 JSON 規范,應用程序不應期望字段的特定排序。

實際上 Gson.toJson(Object object) 不會以隨機順序生成字段。 結果 json 的順序取決於字段名稱的字面順序。

我遇到了同樣的問題,它是通過類中屬性名稱的字面順序解決的。

問題中的示例將始終返回以下 jsonRequest:

{ "bar":"bar", "baz":"baz" }

為了有一個特定的順序,你應該修改字段的名稱,例如:如果你希望baz在第一位,那么bar

public class Foo {
    public String f1_baz;
    public String f2_bar;

    public Foo ( String f1_baz, String f2_bar ) {
        this.f1_baz = f1_baz;
        this.f2_bar = f2_bar;
    }
}

jsonRequest 將是{ "f1_baz ":"baz", "f2_bar":"bar" }

這是我在給定目錄中循環 json 文本文件並使用排序版本覆蓋它們的解決方案:

private void standardizeFormat(File dir) throws IOException {
    File[] directoryListing = dir.listFiles();
    if (directoryListing != null) {
        for (File child : directoryListing) {
            String path = child.getPath();
            JsonReader jsonReader = new JsonReader(new FileReader(path));

            Gson gson = new GsonBuilder().setPrettyPrinting().registerTypeAdapter(LinkedTreeMap.class, new SortedJsonSerializer()).create();
            Object data = gson.fromJson(jsonReader, Object.class);
            JsonWriter jsonWriter = new JsonWriter(new FileWriter(path));
            jsonWriter.setIndent("  ");
            gson.toJson(data, Object.class, jsonWriter);
            jsonWriter.close();
        }
    }
}

private class SortedJsonSerializer implements JsonSerializer<LinkedTreeMap> {
    @Override
    public JsonElement serialize(LinkedTreeMap foo, Type type, JsonSerializationContext context) {
        JsonObject object = new JsonObject();
        TreeSet sorted = Sets.newTreeSet(foo.keySet());
        for (Object key : sorted) {
            object.add((String) key, context.serialize(foo.get(key)));
        }
        return object;
    }
}

這很棘手,因為它取決於當 Type 只是 Object 時 Gson 使用 LinkedTreeMap 的事實。 這是一個可能無法保證的實現細節。 無論如何,這對於我短暫的目的來說已經足夠了......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM