Чтение Java Json / Gson не распознает Integer / Double [duplicate]

Примечание: - Android-телефон должен быть укоренен и не нужен кабель USB.

Установить wifi adb в телефоне android из playstore

ссылка: - https: // play.google.com/store/apps/details?id=com.ttxapps.wifiadb

Для Windows

Я использую эту технику, что очень просто.

1) загрузить adb:

ссылка: https://www.dropbox.com/s/mcxw0yy3jvydupd/adb-setup-1.4.3.exe?dl= 0

2) Выполнить exe: - когда вы видите синий экран, нажмите y.

3) Теперь откройте свой wfi adb apk, просто дайте root-разрешение и обязательно запомните телефон и систему Android в той же сети через Wi-Fi или горячую точку.

4) Откройте Wifi adb apk, вы получите некоторый ip-адрес, например adb connect 192.168.2.134:5555. Обратите внимание, что этот ip может быть очень из системы в систему, теперь поместите эту информацию в свою командную строку и нажмите Enter.

5) Откройте cmd из любой точки входа adb connect 192.168.2.134:5555.

6) Наконец, вы успешно подключились к adb. он покажет сообщение, подобное connected to 192.168.2.140:5555

Для Mac Os

Это самый простой способ и обеспечит автоматическое обновление.

1) Установить homebrew

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2) Установить adb

brew cask install android-platform-tools

3) Начать использовать adb

adb devices

4) Открыть Widi adb apk, вы получите некоторый IP-адрес, например , adb connect 192.168.2.134:5555 Обратите внимание, что этот ip может быть очень из системы в систему, теперь передайте эту информацию на ваш терминал и нажмите Enter.

5) Откройте терминал в mac os из любой точки входа adb connect 192.168.2.134:5555.

6) Наконец, вы успешно подключились к adb. он покажет сообщение, как connected to 192.168.2.140:5555

Я надеюсь, что он вам поможет, спасибо!

6
задан AlexC 8 April 2016 в 20:42
поделиться

4 ответа

1) Вам нужно создать пользовательские JsonDeserializer, а не JsonSerializer, как в вашем вопросе.

2) Я не думаю, что это поведение происходит из Double десериализатора. это больше похоже на проблему json object / map

. Из исходного кода :

case NUMBER:
      return in.nextDouble();

Итак, вы можете попробовать подход с настраиваемым десериализатором для Map<String, Object> (или, если хотите, какую-нибудь более общую карту):

public static class MapDeserializerDoubleAsIntFix implements JsonDeserializer<Map<String, Object>>{

    @Override  @SuppressWarnings("unchecked")
    public Map<String, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        return (Map<String, Object>) read(json);
    }

    public Object read(JsonElement in) {

        if(in.isJsonArray()){
            List<Object> list = new ArrayList<Object>();
            JsonArray arr = in.getAsJsonArray();
            for (JsonElement anArr : arr) {
                list.add(read(anArr));
            }
            return list;
        }else if(in.isJsonObject()){
            Map<String, Object> map = new LinkedTreeMap<String, Object>();
            JsonObject obj = in.getAsJsonObject();
            Set<Map.Entry<String, JsonElement>> entitySet = obj.entrySet();
            for(Map.Entry<String, JsonElement> entry: entitySet){
                map.put(entry.getKey(), read(entry.getValue()));
            }
            return map;
        }else if( in.isJsonPrimitive()){
            JsonPrimitive prim = in.getAsJsonPrimitive();
            if(prim.isBoolean()){
                return prim.getAsBoolean();
            }else if(prim.isString()){
                return prim.getAsString();
            }else if(prim.isNumber()){
                Number num = prim.getAsNumber();
                // here you can handle double int/long values
                // and return any type you want
                // this solution will transform 3.0 float to long values
                if(Math.ceil(num.doubleValue())  == num.longValue())
                   return num.longValue();
                else{
                    return num.doubleValue();
                }
            }
        }
        return null;
    }
}

Чтобы использовать ее, вам нужно будет отдать TypeToken функции registerTypeAdapter и gson.fromJson:

String json="[{\"id\":1,\"quantity\":2,\"name\":\"apple\"}, {\"id\":3,\"quantity\":4,\"name\":\"orange\"}]";

GsonBuilder gsonBuilder = new GsonBuilder();

gsonBuilder.registerTypeAdapter(new TypeToken<Map <String, Object>>(){}.getType(),  new MapDeserializerDoubleAsIntFix());

Gson gson = gsonBuilder.create();
List<Map<String, Object>> l = gson.fromJson(json, new TypeToken<List<Map<String, Object>>>(){}.getType() );

for(Map<String, Object> item : l)
    System.out.println(item);

String serialized = gson.toJson(l);
System.out.println(serialized);

Результат:

{id=1, quantity=2, name=apple}
{id=3, quantity=4, name=orange}
Serialized back to: [{"id":1,"quantity":2,"name":"apple"},{"id":3,"quantity":4,"name":"orange"}]

PS: Это еще один вариант, который вы можете попробовать. Лично я чувствую, что создание пользовательского объекта для вашего json вместо List<Map<String, Integer>> намного более круто и проще для чтения

11
ответ дан varren 5 September 2018 в 10:05
поделиться

Потоковая версия ответа @ varren:

class CustomizedObjectTypeAdapter extends TypeAdapter<Object> {

    private final TypeAdapter<Object> delegate = new Gson().getAdapter(Object.class);

    @Override
    public void write(JsonWriter out, Object value) throws IOException {
        delegate.write(out, value);
    }

    @Override
    public Object read(JsonReader in) throws IOException {
        JsonToken token = in.peek();
        switch (token) {
            case BEGIN_ARRAY:
                List<Object> list = new ArrayList<Object>();
                in.beginArray();
                while (in.hasNext()) {
                    list.add(read(in));
                }
                in.endArray();
                return list;

            case BEGIN_OBJECT:
                Map<String, Object> map = new LinkedTreeMap<String, Object>();
                in.beginObject();
                while (in.hasNext()) {
                    map.put(in.nextName(), read(in));
                }
                in.endObject();
                return map;

            case STRING:
                return in.nextString();

            case NUMBER:
                //return in.nextDouble();
                String n = in.nextString();
                if (n.indexOf('.') != -1) {
                    return Double.parseDouble(n);
                }
                return Long.parseLong(n);

            case BOOLEAN:
                return in.nextBoolean();

            case NULL:
                in.nextNull();
                return null;

            default:
                throw new IllegalStateException();
        }
    }
}

Это измененная версия ObjectTypeAdapter.java . Эти исходные строки:

case NUMBER:
    return in.nextDouble();

заменены следующим:

case NUMBER:
    String n = in.nextString();
    if (n.indexOf('.') != -1) {
        return Double.parseDouble(n);
    }
    return Long.parseLong(n);

В этом коде число считывается как строка, а тип номера выбирается на основе существования точки: number является двойным, только если в его строковом представлении есть точка, и в противном случае она длинна. Такое решение сохраняет исходные значения источника JSON.

Этот модифицированный адаптер можно использовать как универсальный, если вы можете зарегистрировать его для типа Object, но Gson предотвращает его:

// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);

Вы должны зарегистрируйте адаптер этого типа для тех типов, которые вам нужны, например Map и List:

CustomizedObjectTypeAdapter adapter = new CustomizedObjectTypeAdapter();
Gson gson = new GsonBuilder()
        .registerTypeAdapter(Map.class, adapter)
        .registerTypeAdapter(List.class, adapter)
        .create();

Теперь Gson может десериализовать числа как .

7
ответ дан cybersoft 5 September 2018 в 10:05
поделиться

Это отлично работает для меня:

private static class DoubleSerializer implements JsonSerializer<Double> {
    @Override
    public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
        return src == src.longValue() ? new JsonPrimitive(src.longValue()) : new JsonPrimitive(src);
    }
}

Gson gson = new GsonBuilder().registerTypeAdapter(Double.class, new DoubleSerializer()).setPrettyPrinting().create();
1
ответ дан Leon 5 September 2018 в 10:05
поделиться

Вы должны использовать public T fromJson (JsonElement json, Type typeOfT)

public void keepsIntsAsIs(){
        String json="[{\"id\":1,\"quantity\":2},{\"id\":3,\"quantity\":4}]";
        GsonBuilder gsonBuilder = new GsonBuilder();
        Gson gson = gsonBuilder.create();
        Type objectListType = new TypeToken<List<Map<String, Integer>>>(){}.getType();
        List<Map<String, Integer>> l = gson.fromJson(json, objectListType);
        for(Map<String, Integer> item : l){
            System.out.println(item);
        }
    }

Выход:

{id=1, quantity=2}
{id=3, quantity=4}

[EDIT]

Если не все поля являются целыми числами, то один из способов решить это - сопоставить json с объектом и определить десериализатор для этого объекта.

Ниже приведен пример.

Я сопоставляю json с IdQuantityName, а IdQuantityDeserializer - десериализатор json.

package com.foo;



import java.lang.reflect.Type;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;

public class TestGSON {

public void keepsIntsAsIs(){
    String json="[{\"id\":1,\"quantity\":2,\"name\":\"apple\"},{\"id\":3,\"quantity\":4,\"name\":\"orange\"}]";
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeHierarchyAdapter(IdQuantityName.class, new IdQuantityDeserializer());
    gsonBuilder.registerTypeAdapter(IdQuantityName.class, new IdQuantityDeserializer());

    Gson gson = gsonBuilder.create();
    Type objectListType = new TypeToken<List<IdQuantityName>>(){}.getType();
    List<IdQuantityName> l = gson.fromJson(json,objectListType);
    for (IdQuantityName idQuantityName : l) {
        System.out.println(idQuantityName);
    }
}



class IdQuantityName{
    private int id;
    private Object quantity;
    private String name;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public Object getQuantity() {
        return quantity;
    }
    public void setQuantity(Object quantity) {
        this.quantity = quantity;
    }
    public Object getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "IdQuantityName [id=" + id + ", quantity=" + quantity
                + ", name=" + name + "]";
    }



}
private  class IdQuantityDeserializer implements JsonDeserializer<IdQuantityName>{

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

        JsonObject jo = json.getAsJsonObject();

        IdQuantityName idq = new IdQuantityName();
        idq.setId(jo.get("id").getAsInt());
        idq.setName(jo.get("name").getAsString());

        JsonElement jsonElement = jo.get("quantity");
        if(jsonElement instanceof JsonPrimitive){
            if(((JsonPrimitive) jsonElement).isNumber()){
                idq.setQuantity(jsonElement.getAsInt());
            };
        }
        return idq;

    }
}
public static void main(String[] args) {
    new TestGSON().keepsIntsAsIs();
}
}
1
ответ дан Sanj 5 September 2018 в 10:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: