Подтвердить что ты не робот

Как сохранить последовательность полей в сериализации Gson

Похоже, что Gson.toJson(объект 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)

Спасибо.

4b9b3361

Ответ 1

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

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

Ответ 2

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

Это поддерживает порядок, указанный вами в сериализаторе.

См. также:

Ответ 3

Здесь мое решение для циклизации текстовых файлов 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, когда Type является просто Object. Это детали реализации, которые, вероятно, не гарантируются. Во всяком случае, это достаточно хорошо для моих непродолжительных целей...

Ответ 4

На самом деле Gson.toJson(Object object) не генерирует поля в случайном порядке. Порядок приведенного json зависит от буквенной последовательности имен полей.

У меня была такая же проблема, и она была решена буквальным порядком имен свойств в классе.