Подтвердить что ты не робот

Gson. Дезериализуйте целые числа как целые числа, а не как двойные

У меня есть объект json с внутренними значениями. И я хочу десериализировать его на Карте. Все в порядке, за исключением преобразования целых чисел в парные. Пример:

{"id":1, "inner_obj":{"key":"value","num":666,"map":{"key":"value"}}}

выполняет десериализацию (map.toString()):

{id=1.0, inner_obj={key=value, num=666.0, map={key=value}}}

Есть ли простой способ десериализации "id" и "num" как целые числа, а не как пары?

4b9b3361

Ответ 1

В JSON нет целочисленного типа. 1 и 1.0 - то же самое. Вам нужно проанализировать, что от 1.0 до 1 в вашем коде. Или вам нужно сопоставить JSON с некоторым классом VO и четко определить тип полей класса, чтобы GSON мог понять, что вы ищете.

Ответ 2

JSON имеет только один тип Number, и парсер не может автоматически указать, к какому типу его преобразовать.

Если вы не собираетесь использовать строго типизированный граф объектов, рассмотрите использование JsonElement типов:

JsonObject root = new Gson().fromJson(json, JsonObject.class);
int num = root.getAsJsonObject("inner_obj").get("num").getAsInt();

Ответ 3

Это мой код

private static class MapDeserializer implements JsonDeserializer<Map<String,Object>> {
    public Map<String,Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)  throws JsonParseException {
        Map<String,Object> m  = new LinkedHashMap<String, Object>();
        JsonObject jo = json.getAsJsonObject();
        for (Entry<String, JsonElement>  mx : jo.entrySet()){
            String key = mx.getKey();
            JsonElement v = mx.getValue();
            if(v.isJsonArray()){
                m.put(key, g.fromJson(v, List.class));
            }else if(v.isJsonPrimitive()){
                 Number num = null;
                  try {
                      num = NumberFormat.getInstance().parse(v.getAsString());
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                m.put(key,num);
            }else if(v.isJsonObject()){
                m.put(key,g.fromJson(v, Map.class));    
            }

        }
      return m;
   }
}

private static class ListDeserializer implements JsonDeserializer<List<Object>> {
    public List<Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)  throws JsonParseException {
        List<Object> m  = new ArrayList<Object>();
        JsonArray arr = json.getAsJsonArray();
        for (JsonElement jsonElement : arr) {
            if(jsonElement.isJsonObject()){
                m.add(g.fromJson(jsonElement, Map.class));
            }else if(jsonElement.isJsonArray()){
                m.add(g.fromJson(jsonElement, List.class));
            }else if(jsonElement.isJsonPrimitive()){
                Number num = null;
                try {
                  num = NumberFormat.getInstance().parse(jsonElement.getAsString());
                } catch (Exception e) {
                }
                m.add(num);
            }
        }
      return m;
   }
}

private static Gson g = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserializer()).registerTypeAdapter(List.class, new ListDeserializer()).setDateFormat("yyyy-MM-dd HH:mm:ss").serializeNulls().create();

Ответ 4

Ищет решение самой проблемы с вложенной Картой, а "이종은" выше был первым ответом, который действительно помог в нетривиальных случаях использования.

Поскольку вышеописанное решение обрабатывается только номером I, я обновил решение, обеспечивающее общую возможность синтаксического анализа для String и booleans, см. обновленный код ниже:

private static class MapDeserializer implements JsonDeserializer<Map<String, Object>> {

    public Map<String, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        Map<String, Object> m = new LinkedHashMap<String, Object>();
        JsonObject jo = json.getAsJsonObject();
        for (Entry<String, JsonElement> mx : jo.entrySet()) {
            String key = mx.getKey();
            JsonElement v = mx.getValue();
            if (v.isJsonArray()) {
                m.put(key, g.fromJson(v, List.class));
            } else if (v.isJsonPrimitive()) {
                Number num = null;
                ParsePosition position=new ParsePosition(0);
                String vString=v.getAsString();
                try {
                  num = NumberFormat.getInstance(Locale.ROOT).parse(vString,position);
                } catch (Exception e) {
                }
                //Check if the position corresponds to the length of the string
                if(position.getErrorIndex() < 0 && vString.length() == position.getIndex()) {
                  if (num != null) {
                    m.put(key, num);
                    continue;
                  }
                }
                JsonPrimitive prim = v.getAsJsonPrimitive();
                if (prim.isBoolean()) {
                    m.put(key, prim.getAsBoolean());
                } else if (prim.isString()) {
                    m.put(key, prim.getAsString());
                } else {
                    m.put(key, null);
                }

            } else if (v.isJsonObject()) {
                m.put(key, g.fromJson(v, Map.class));
            }

        }
        return m;
    }
}

private static class ListDeserializer implements JsonDeserializer<List<Object>> {

    public List<Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        List<Object> m = new ArrayList<Object>();
        JsonArray arr = json.getAsJsonArray();
        for (JsonElement jsonElement : arr) {
            if (jsonElement.isJsonObject()) {
                m.add(g.fromJson(jsonElement, Map.class));
            } else if (jsonElement.isJsonArray()) {
                m.add(g.fromJson(jsonElement, List.class));
            } else if (jsonElement.isJsonPrimitive()) {
                Number num = null;
                try {
                    num = NumberFormat.getInstance().parse(jsonElement.getAsString());
                } catch (Exception e) {
                }
                if (num != null) {
                    m.add(num);
                    continue;
                }
                JsonPrimitive prim = jsonElement.getAsJsonPrimitive();
                if (prim.isBoolean()) {
                    m.add(prim.getAsBoolean());
                } else if (prim.isString()) {
                    m.add(prim.getAsString());
                } else {
                    m.add(null);
                }
            }
        }
        return m;
    }
}

private static Gson g = new GsonBuilder().registerTypeAdapter(Map.class, new MapDeserializer()).registerTypeAdapter(List.class, new ListDeserializer()).setDateFormat("yyyy-MM-dd HH:mm:ss").create();

Ответ 5

Вот мой пример: первая часть - это определение класса, в котором есть поле типа int.

import com.google.api.client.util.Key;

public class Folder {

    public static final String FIELD_NAME_CHILD_COUNT = "childCount";

    @Key(FIELD_NAME_CHILD_COUNT)
    public final int childCount;

    public Folder(int aChildCount) {
        childCount = aChildCount;
    }
}

Затем TypeAdapter преобразует тип номера в Gson в объект Java.

GsonBuilder gsb = new GsonBuilder();

gsb.registerTypeAdapter(Folder.class, new JsonDeserializer<Folder>() {

            @Override
            public Folder deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

                int value = json.getAsJsonObject().get("childCount").getAsJsonPrimitive().getAsInt();

                return new Folder(value);

            }
        }
);

Третья часть - это тестовые данные, и она работает.

String gsonData =  new String("\"folder\":{\"childCount\":0}");