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

时间:2011-06-16 00:15:17

标签: java json serialization gson

似乎像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 now can be { "bar":"bar", "baz":"baz" } (which is correct)
    //             and can be { "baz":"baz", "bar":"bar" } (which is a wrong sequence)

感谢。

4 个答案:

答案 0 :(得分:25)

您需要创建自定义JSON序列化程序。

E.g。

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);
// ...

这样可以保持序列化程序中指定的顺序。

另见:

答案 1 :(得分:19)

如果GSON不支持字段顺序的定义,则可以使用其他库。例如,Jackson允许使用@JsonPropertyOrder来定义它。必须指定一个自己的自定义序列化器对我来说似乎是非常多的工作。

是的,我同意根据JSON规范,应用程序不应该期望字段的特定排序。

答案 2 :(得分:2)

这是我的解决方案,用于循环给定目录中的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;
    }
}

它非常hacky,因为它取决于当Type只是Object时Gson使用LinkedTreeMap这一事实。这是一个可能无法保证的实现细节。无论如何,这对我的短暂目的来说已经足够了......

答案 3 :(得分:0)

实际上,Gson.toJson(Object object)不会以随机顺序生成字段。产生的json的顺序取决于字段名称的字面顺序。

我遇到了同样的问题,并且通过类中属性名称的字面顺序解决了。