Как сохранить последовательность полей в сериализации Gson - PullRequest
36 голосов
/ 16 июня 2011

Похоже, что Gson.toJson (объектный объект) генерирует код 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)

Спасибо.

Ответы [ 3 ]

26 голосов
/ 16 июня 2011

Вам нужно создать собственный сериализатор 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);
// ...

.Вы указали в сериализаторе.

См. также:

20 голосов
/ 20 июня 2011

Если GSON не поддерживает определение порядка полей, существуют другие библиотеки, которые поддерживают. Джексон позволяет определить это, например, с помощью @JsonPropertyOrder. Необходимость указать свой собственный сериализатор кажется мне ужасной работой.

И да, я согласен с тем, что согласно спецификации JSON приложение не должно ожидать определенного упорядочения полей.

2 голосов
/ 04 августа 2015

Вот мое решение для зацикливания текстовых файлов 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;
    }
}

Это довольно забавно, потому что это зависит от того факта, что Gson использует LinkedTreeMap, когдаТип это просто Объект.Это детали реализации, которые, вероятно, не гарантированы.Во всяком случае, этого достаточно для моих недолговечных целей ...

...