8

我正在使用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对象并将对象移动DurationStep对象,如下所示:

"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。

4

4 回答 4

7

您可以通过编写然后为.StepDurationData

// 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;
    }
}
于 2012-06-05T15:12:35.460 回答
2

在这种情况下,我注册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;
    }

}
于 2020-02-24T15:33:24.350 回答
0

我认为在 gson 中没有漂亮的方法可以做到这一点。也许从初始 json 中获取 java 对象(映射),删除数据,放入持续时间并序列化为 json:

Map initial = gson.fromJson(initialJson);

// Replace data with duration in this map
Map converted = ...

String convertedJson = gson.toJson(converted);
于 2012-06-05T14:34:30.993 回答
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 并在其中排除“数据”来删除,只留下需要展开硬编码的元素。

于 2019-01-07T19:43:45.427 回答