Как настроить gson для исключения 0 целых значений

У меня есть класс Java с множеством целочисленных полей и когда я хочу сериализовать их в json-строку из-за того, что некоторые из них не могут иметь никакого значения, следовательно, после сериализации всех целых чисел получить нуль в качестве значений! Я хочу, чтобы config gson не сериализовал их, если у них нет каких-либо значений.

например, у меня есть этот класс:

class Example {
   String title = "something";
   int id = 22;
   int userId;
} 

по умолчанию gson дает мне этот результат:

{
   "title" : "something",
   "id" : 22,
   "userId" : 0
}

но я не хочу, чтобы userId был сериализован, когда его значение равно 0. поэтому json должен быть:

{
   "title" : "something",
   "id" : 22
}

для объектов по умолчанию gson не сериализует нулевые объекты, есть способ config gson не сериализовать 0 чисел

Ответ 1

Мы должны просто использовать класс Integer (Integer javadoc).

class Example {
   String title = "something";
   Integer id = 22;
   Integer userId;
}

Ответ 2

Вы можете написать пользовательский TypeAdapter.

public class ExampleTypeAdapter extends TypeAdapter<Example> {

    @Override
    public Example read(com.google.gson.stream.JsonReader in)
            throws IOException {
        final Example example = new Example();

        in.beginObject();
        while (in.hasNext()) {
            String name = in.nextName();
            if ("title".equals(name)) {
                example.title = in.nextString();
            } else if ("id".equals(name)) {
                example.id = in.nextInt();
            } else if ("userId".equals(name)) {
                example.userId = in.nextInt();
            }
        }
        in.endObject();

        return example;
    }

    @Override
    public void write(com.google.gson.stream.JsonWriter out, Example example)
            throws IOException {
        out.beginObject();
        out.name("title").value(example.title);

        if(example.id != 0) {
            out.name("id").value(example.id);
        }

        if(example.userId != 0) {
            out.name("userId").value(example.userId);
        }

        out.endObject();
    }
}

Попробуйте с кодом ниже:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Example.class, new ExampleTypeAdapter());
gsonBuilder.setPrettyPrinting();

Gson gson = gsonBuilder.create();

Example example = new Example();
example.title = "mytitle";
example.id = 1234;
example.userId = 0;

final String json = gson.toJson(example);
System.out.println(json);

Выход будет:

 {
   "title": "my title",
   "id": 1234
 }

Примечание. Важная часть находится в методе write нашего пользовательского TypeAdapter.

Ответ 3

Создайте этот адаптер типа JSON. Его можно использовать везде, где вы хотите игнорировать запись нулевых значений. Он также может быть адаптирован к длинным, двойным и другим числовым типам. Вы также можете изменить его, чтобы игнорировать запись значения, отличного от нуля.

Да, я знаю, что Autoboxing и Unboxing используются неявно, но вы не можете указать примитивный тип для универсального типа.

public class IntIgnoreZeroAdapter extends TypeAdapter<Integer> {
    private static Integer INT_ZERO = Integer.valueOf(0);

    @Override
    public Integer read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return 0;
        }

        return in.nextInt();
    }

    @Override
    public void write(JsonWriter out, Integer data) throws IOException {
        if (data == null || data.equals(INT_ZERO)) {
            out.nullValue();
            return;
        }

        out.value(data.intValue());
    }
}

Измените свой класс, чтобы указать IntIgnoreZeroAdapter для членов типа int.

class Example {
   String title = "something";

   @JsonAdapter(IntIgnoreZeroAdapter.class)
   int id = 22;

   @JsonAdapter(IntIgnoreZeroAdapter.class)
   int userId;
} 

Ответ 4

Я хочу настроить gson, чтобы не сериализовать их, если они не имеют каких-либо значений.

Это предложение заставляет меня думать, что вы неправильно понимаете, как переменные и значения работают в Java. Обратите внимание, что все переменные в Java имеют значение, даже если вы не назначаете им однозначно. Если вы объявляете int и не присваиваете ему значение, вам будет присвоено значение по умолчанию 0. Итак, это:

int userId;

эквивалентно этому:

int userId = 0;

https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Хотя ответ Нитина Гаванде сам по себе неверен, я все равно рекомендовал бы его, так как я предполагаю, что, вероятно, вы хотите. null значение для Integer является более надежным представлением значения, которое никогда не назначалось, чем нулевое значение для int (обычно). И это позволяет вам использовать GSON удобную функцию "не сериализовать нули".