GSON: Как переместить поля в родительский объект

Я использую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, но в методе записи я не могу добавить свой объект продолжительности в JsonWriter.

Ответы на вопрос(3)

Решение Вопроса

Вы, вероятно, можете сделать это, написав, а затем зарегистрировавпользовательский сериализатор заStepи убедившись, что внутри него вы работаете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 несколько раз. Но это представляетkind of thing Вы хотите сделать:

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;
    }
}
 05 июн. 2012 г., 18:32
этоreally зависит. Покажите пример с двумя дополнительными полями, и я посмотрю, что я могу придумать. Предостережение: мой ответ основан на документации Gson. Я никогда раньше не делал таких странных вещей.
 05 июн. 2012 г., 19:04
@DennisMadsen - я обновил свой ответ, чтобы отразить ваши изменения. Удачи.
 dhrm05 июн. 2012 г., 18:41
Я обновил свой вопрос дополнительными полями внутри объекта данных.
 dhrm05 июн. 2012 г., 17:43
Мне нужно толькоserialize, такdeserialize не важно. Выше было просто пример моей структуры. Фактически мой объект данных содержит дополнительные поля, которые необходимо включить вtoJsonTree, Любая подсказка, как я могу это сделать?
 dhrm05 июн. 2012 г., 19:22
Благодарю. Есть ли способ создатьstep переменная из шага src и просто удалите его объект данных? Если это возможно, мне не нужно было бы снова добавлять начальное и конечное имя.

Я не думаю, что есть прекрасный способ сделать это в gson. Может быть, получить объект java (Map) из исходного json, удалить данные, указать продолжительность и сериализовать в json:

Map initial = gson.fromJson(initialJson);

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

String convertedJson = gson.toJson(converted);

Столкнулся с той же проблемой. Ответ @ArjunShunkar указал мне правильное направление. Я исправил это, написав собственный Serializer, но немного по-другому:

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;
    }
}

Это может быть улучшено далее, «имя_старки» и & quot; имя_конца & quot; реквизиты все еще жестко закодированы. Можно удалить, перейдя через набор записей для корневого объекта и исключив «данные»; там, оставляя только элемент, который должен быть развернут в жестком коде.

Ваш ответ на вопрос