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)
ありがとう。
GSONがフィールドオーダーの定義をサポートしていない場合は、サポートしている他のライブラリがあります。 Jackson は、たとえば@JsonPropertyOrderでこれを定義できます。独自のカスタムシリアライザーを指定する必要があるのは、私にとっては大変な作業のようです。
そして、はい、JSON仕様に従って、アプリケーションはフィールドの特定の順序を期待すべきではないことに同意します。
カスタム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.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を使用するという事実に依存しているため、かなりハッキーです。これは、おそらく保証されない実装の詳細です。とにかく、それは私の短命の目的には十分です...