2014-11-27 12 views
5

Mam do czynienia z interfejsem API, który wysyła liczby całkowite (1 = true, other = false), aby reprezentować wartości logiczne.GSON Integer to Boolean dla konkretnych pól

Widziałem this question and answer, ale muszę być w stanie określić, do którego pola powinno to dotyczyć, ponieważ czasami liczba całkowita jest w rzeczywistości liczbą całkowitą.

EDIT: Przychodzące JSON mógłby wyglądać następująco (może być też String zamiast int, etc ...):

{ 
    "regular_int": 1234, 
    "int_that_should_be_a_boolean": 1 
} 

Muszę sposób określić, że int_that_should_be_a_boolean powinien być analizowany jako boolean i regular_int powinny być analizowane jako liczba całkowita.

Odpowiedz

10

Będziemy dostarczać Gson z małym hakiem, niestandardowym Deserializatora dla wartości logicznych, czyli klasy, która implementuje interfejs JsonDeserializer<Boolean>:

CustomBooleanTypeAdapter

import java.lang.reflect.Type; 
import com.google.gson.*; 
class BooleanTypeAdapter implements JsonDeserializer<Boolean> 
{ 
     public Boolean deserialize(JsonElement json, Type typeOfT, 
      JsonDeserializationContext context) throws JsonParseException 
     { 
      int code = json.getAsInt(); 
      return code == 0 ? false : 
        code == 1 ? true : 
       null; 
     } 
} 

Aby z niego skorzystać musimy zmień trochę sposób, w jaki otrzymujemy instancję odwzorowującą Gson, używając obiektu fabrycznego, GsonBuilder, wspólny wzór do używania GSON jest tutaj.

GsonBuilder builder = new GsonBuilder(); 
builder.registerTypeAdapter(Boolean.class, new BooleanTypeAdapter()); 
Gson gson = builder.create(); 

Dla prymitywnego użytku Rodzaj poniżej jeden

GsonBuilder builder = new GsonBuilder(); 
    builder.registerTypeAdapter(boolean.class, new BooleanTypeAdapter()); 
    Gson gson = builder.create(); 

Ciesz JSON analizowania!

+1

Dzięki! Jeśli rozumiem poprawnie, za każdym razem, gdy próbuję deserializować za pomocą tego zestawu 'BooleanTypeAdapter', każda' 'boolean' będzie traktowana w ten sposób? – Eliezer

+0

@Maheshwar Ligade A co z pytaniem ** określone pola ** część? To rozwiązanie nie działa, gdy odpowiedzi zawierają normalną wartość całkowitą, np. 'Quantity: 0' ten klucz nie może być reprezentowany jako' Boolean' –

0

Jeśli dobrze rozumiem, chcesz znormalizować lub masować wartość na przychodzącym JsonReader od int do czegoś innego, jak boolean.

Jeśli tak, prawdopodobnie należy utworzyć klasę adaptera, która rozszerza TypeAdapter <YourFieldNameType> i zastępuje read(). Otrzymujesz wartość z nextInt(), a następnie zwracasz odpowiednią wartość logiczną na podstawie jej wartości. Być może trzeba będzie sprawdzić wartości puste, w zależności od konfiguracji parsera.

Jeśli zachodzi taka potrzeba, można przesłonić metodę write() w tej samej klasie adaptera, aby wymusić wartość booleans w kodzie klienta na liczby całkowite dla JsonWriter.

[Edycja]

Dla odniesienia, to jest przykład mego TypeAdapter, przekształcająca się „Polecenia” klasy enum/do całkowitej.

package com.company.product.json; 

import static com.company.product.Commands.*; 

import java.io.IOException; 
import java.util.logging.Logger; 

import com.google.gson.TypeAdapter; 
import com.google.gson.stream.JsonReader; 
import com.google.gson.stream.JsonWriter; 
import com.company.product.Commands; 
import com.company.product.client.ClientSocket; 

/** 
* Adapter for Command handling. 
* 
* We write out the CommandName as an Integer, and read it in as a Commands constant. 
* 
* This satisfies the requirement that the CommandName by represented by JSON as an int, but allows 
* us to deserialize it to a Commands object on read. 
* 
* @author jdv 
* @see com.company.product.Command#commandName CommandName 
*/ 
public class CommandsAdapter extends TypeAdapter<Commands> { 

    private static final Logger logger = Logger.getLogger(ClientSocket.class.getPackage().getName()); 

    /* 
    * (non-Javadoc) Deserialize the JSON "CommandName" integer into the corresponding Commands 
    * constant object. 
    * 
    * @see com.google.gson.TypeAdapter#read(com.google.gson.stream.JsonReader) 
    */ 
    @Override 
    public Commands read(JsonReader in) throws IOException { 

    final int command; 
    try { 
     command = in.nextInt(); 

    } catch (IllegalStateException e) { 
     logger.severe("Unable to read incoming JSON stream: " + e.getMessage()); 
     throw new IOException(e); 

    } catch (NumberFormatException e) { 
     logger 
      .severe("Unable to read and convert CommandName Integer from the incoming JSON stream: " 
       + e.getMessage()); 
     throw new IOException(e); 
    } 

    // Let's not risk using a bad array index. Not every command is expected 
    // by the WebSocket handlers, but we should do our best to construct 
    // a valid Commands object. 
    if (command < NO_OP.getValue() || command > LAST_COMMAND.getValue()) { 
     throw new IOException(new IllegalArgumentException(
      "Unexpected value encountered for Commands constant: " + command)); 
    } else { 
     return Commands.values()[command]; 
    } 
    } 

    /* 
    * (non-Javadoc) Serialize Commands object constants as their Integer values. 
    * 
    * @see com.google.gson.TypeAdapter#write(com.google.gson.stream.JsonWriter, java.lang.Object) 
    */ 
    @Override 
    public void write(JsonWriter out, Commands value) throws IOException { 
    out.value(value.getValue()); 
    } 

} 

ten zasadniczo dopasowuje przychodzące i wychodzące ops na „nazwa_polecenia” odcinkach param lokalnie reprezentowane jako „Polecenia” wyliczenia i jako całkowita odległość. Coś związanego z tym wyliczaniem komend jest filtrowane za pośrednictwem tej klasy adaptera, która zastępuje read() i write(). W efekcie prowadzi to do współpracy z WebSocket, ale żadna z tych rzeczy nie ma znaczenia dla celów tej dyskusji. HTH.

+0

Załóżmy, że istnieją pewne wartości całkowite, które chcę traktować jako wartości logiczne, i niektóre, które chcę traktować jako liczby całkowite, o czym pisałem w ostatnim zdaniu pytania. – Eliezer

+0

Jeśli pochodzą z tego samego serializowanego pola na JsonReader, będziesz musiał umieścić dodatkową logikę w read(), aby podjąć decyzję i zwrócić właściwą rzecz.Ale w skrócie, jeśli chcesz zmostkować typy przychodzące lub wychodzące do innego typu, musisz utworzyć klasę TypeAdapter dla tych typów. – jdv

+0

Zaktualizowałem pytanie, aby wyjaśnić problem nieco jaśniej. – Eliezer

Powiązane problemy