我正在使用Google GSON将我的Java对象转换为JSON。
目前我的结构如下:
"Step": {
"start_name": "Start",
"end_name": "End",
"data": {
"duration": {
"value": 292,
"text": "4 min."
},
"distance": {
"value": 1009.0,
"text": "1 km"
},
"location": {
"lat": 59.0000,
"lng": 9.0000,
"alt": 0.0
}
}
}
目前Duration
对象位于Data
对象中。我想跳过Data
对象并将Duration
对象移动到Step
对象,如下所示:
"Step": {
"start_name": "Start",
"end_name": "End",
"duration": {
"value": 292,
"text": "4 min."
},
"distance": {
"value": 1009.0,
"text": "1 km"
},
"location": {
"lat": 59.0000,
"lng": 9.0000,
"alt": 0.0
}
}
如何使用GSON执行此操作?
编辑:我尝试使用TypeAdapter修改Step.class,但在write-method中我无法将持续时间对象添加到JsonWriter。答案 0 :(得分:3)
您可以通过编写,然后为Step
注册custom serializer,并确保在其中使用Duration
等代替Data
来完成此操作。
// registering your custom serializer:
GsonBuilder builder = new GsonBuilder ();
builder.registerTypeAdapter (Step.class, new StepSerializer ());
Gson gson = builder.create ();
// now use 'gson' to do all the work
下面的自定义序列化程序的代码,我正在写下我的头脑。它错过了异常处理,可能无法编译,并且会减慢重复创建Gson
实例的速度。但它代表了你想要做的那种事情:
class StepSerializer implements JsonSerializer<Step>
{
public JsonElement serialize (Step src,
Type typeOfSrc,
JsonSerializationContext context)
{
Gson gson = new Gson ();
/* Whenever Step is serialized,
serialize the contained Data correctly. */
JsonObject step = new JsonObject ();
step.add ("start_name", gson.toJsonTree (src.start_name);
step.add ("end_name", gson.toJsonTree (src.end_name);
/* Notice how I'm digging 2 levels deep into 'data.' but adding
JSON elements 1 level deep into 'step' itself. */
step.add ("duration", gson.toJsonTree (src.data.duration);
step.add ("distance", gson.toJsonTree (src.data.distance);
step.add ("location", gson.toJsonTree (src.data.location);
return step;
}
}
答案 1 :(得分:0)
我认为在gson中没有漂亮的方法。也许从初始json获取java对象(Map),删除数据,将持续时间和序列化添加到json:
Map initial = gson.fromJson(initialJson);
// Replace data with duration in this map
Map converted = ...
String convertedJson = gson.toJson(converted);
答案 2 :(得分:0)
遇到同样的问题。 @ArjunShunkar的回答为我指明了正确的方向。我通过编写自定义序列化器对其进行了修复,但略有不同:
public class StepSerializer implements JsonSerializer<Step> {
@Override
public JsonElement serialize(Step src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject step = new JsonObject();
step.add ("start_name", context.serialize(src.start_name);
step.add ("end_name", context.serialize(src.end_name);
JsonObject data = context.serialize(src.data).getAsJsonObject();
data.entrySet().forEach(entry -> {
step.add(entry.getKey(), entry.getValue());
});
return step;
}
}
这可以进一步改善,“ start_name”和“ end_name”道具仍然是硬编码的。可以通过查看根对象的entrySet并在其中排除“数据”来删除,仅保留需要进行硬编码的元素。
答案 3 :(得分:0)
在这种情况下,我为嵌套的TypeAdapter
域注册了data
。在适配器data
的字段中,将其添加到父对象。无需创建用于封闭类的适配器。
public class Step {
private String startName;
private endName;
@JsonAdapter(JsonFlatMapAdapter.class)
private Map<String, Object> data;
...
}
public class JsonFlatMapAdapter extends TypeAdapter<Map<String, Object>> {
@Override
public void write(JsonWriter out, Map<String, Object> value) throws IOException {
out.nullValue();
Gson gson = new Gson();
value.forEach((k,v) -> {
try {
out.name(k).jsonValue(gson.toJson(v));
} catch (IOException e) {
}
});
}
@Override
public Map<String, Object> read(JsonReader in) throws IOException {
return null;
}
}