Java GSON:如何将字段移动到父对象
我正在使用将Java对象转换为JSON 目前我有以下结构:Java GSON:如何将字段移动到父对象,java,json,gson,Java,Json,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
"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
}
}
}
当前,持续时间
对象位于数据
对象内。我想跳过数据
对象,并将持续时间
对象移动到步骤
对象,如下所示:
"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方法中,我无法将duration对象添加到JsonWriter。我认为在gson中没有更好的方法。可能从初始json获取java对象(映射),删除数据,设置持续时间并序列化为json:
Map initial = gson.fromJson(initialJson);
// Replace data with duration in this map
Map converted = ...
String convertedJson = gson.toJson(converted);
您可能可以通过编写,然后为
步骤
注册一个,并确保在其中使用持续时间
等,而不是数据
来完成此操作
// 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;
}
}
类StepSerializer实现JsonSerializer
{
公共JsonElement序列化(步骤src,
SRC的类型,
JsonSerializationContext(上下文)
{
Gson-Gson=新的Gson();
/*无论何时序列化步骤,
正确序列化包含的数据*/
JsonObject步骤=新建JsonObject();
步骤.add(“启动名称”,gson.toJsonTree(src.start\u名称);
步骤.add(“end_name”,gson.toJsonTree(src.end_name);
/*注意我是如何在“数据”中深入挖掘两个层次的
JSON元素深入“步骤”本身1级*/
添加步骤(“持续时间”,gson.toJsonTree(src.data.duration);
添加步骤(“距离”,gson.toJsonTree(src.data.distance);
步骤.add(“位置”,gson.toJsonTree(src.data.location);
返回步骤;
}
}
遇到了同样的问题。@arjunsunkar的答案为我指明了正确的方向。我通过编写自定义序列化程序修复了它,但略有不同:
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;
}
}
公共类StepSerializer实现JsonSerializer{
@凌驾
公共JsonElement序列化(步骤src,类型typeOfSrc,JsonSerializationContext){
JsonObject步骤=新建JsonObject();
step.add(“start\u name”,context.serialize(src.start\u name);
step.add(“end\u name”,context.serialize(src.end\u name);
JsonObject data=context.serialize(src.data).getAsJsonObject();
data.entrySet().forEach(条目->{
添加(entry.getKey(),entry.getValue());
});
返回步骤;
}
}
这可以进一步改进,“开始名称”和“结束名称”道具仍然是硬编码的。可以通过检查根对象的入口集并排除其中的“数据”来删除道具,只留下需要展开硬编码的元素。在这种情况下,我为嵌套的
数据
字段注册类型适配器
。在适配器中,数据
的字段被添加到父对象t、 不需要为封闭类创建适配器
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;
}
}
公共类步骤{
私有字符串startName;
私有端名;
@JsonAdapter(JsonFlatMapAdapter.class)
私有地图数据;
...
}
公共类JsonFlatMapAdapter扩展了TypeAdapter{
@凌驾
public void write(JsonWriter out,Map值)抛出IOException{
out.nullValue();
Gson Gson=新的Gson();
forEach值((k,v)->{
试一试{
out.name(k).jsonValue(gson.toJson(v));
}捕获(IOE异常){
}
});
}
@凌驾
公共映射读取(JsonReader in)引发IOException{
返回null;
}
}
我只需要序列化
,所以反序列化
并不重要。上面只是我结构的一个例子。事实上,我的数据对象包含额外的字段,需要包含在toJsonTree
中。有什么线索吗?这取决于具体情况。显示一个包含两个额外字段的示例,我将看看我能想到什么。注意:我的答案是基于Gson文档的。我以前从未做过这样奇怪的事情。我用数据对象中的附加字段更新了我的问题。@DennisMadsen-我更新了我的答案以反映您的更改。祝您好运。谢谢。有没有办法从src step和只要删除它的数据对象?如果可能的话,我就不必再添加开始和结束名称了。