[英]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.