Ответ 1
В JSON нет целочисленного типа. 1 и 1.0 - то же самое. Вам нужно проанализировать, что от 1.0 до 1 в вашем коде. Или вам нужно сопоставить JSON с некоторым классом VO и четко определить тип полей класса, чтобы 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" как целые числа, а не как пары?
В JSON нет целочисленного типа. 1 и 1.0 - то же самое. Вам нужно проанализировать, что от 1.0 до 1 в вашем коде. Или вам нужно сопоставить JSON с некоторым классом VO и четко определить тип полей класса, чтобы GSON мог понять, что вы ищете.
JSON имеет только один тип Number, и парсер не может автоматически указать, к какому типу его преобразовать.
Если вы не собираетесь использовать строго типизированный граф объектов, рассмотрите использование JsonElement типов:
JsonObject root = new Gson().fromJson(json, JsonObject.class);
int num = root.getAsJsonObject("inner_obj").get("num").getAsInt();
Это мой код
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();
Ищет решение самой проблемы с вложенной Картой, а "이종은" выше был первым ответом, который действительно помог в нетривиальных случаях использования.
Поскольку вышеописанное решение обрабатывается только номером 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();
Вот мой пример: первая часть - это определение класса, в котором есть поле типа 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}");