2014-11-27 9 views
5

Ho a che fare con un'API che restituisce interi (1 = true, other = false) per rappresentare i booleani.Numero intero GSON a Boolean per campi specifici

Ho visto this question and answer, ma ho bisogno di essere in grado di specificare a quale campo questo deve essere applicato, poiché alcune volte un intero è in realtà un numero intero.

EDIT: Il JSON in entrata potrebbe assomigliare a questo (potrebbe anche essere String invece di int, ecc ...):

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

Ho bisogno di un modo per specificare che int_that_should_be_a_boolean dovrebbe essere analizzato come un valore booleano e regular_int devono essere analizzati come un numero intero.

risposta

10

Forniremo GSON con un po 'gancio, un deserializzatore personalizzato per booleani, cioè una classe che implementa l'interfaccia 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; 
     } 
} 

di usarlo abbiamo bisogno di cambia un po 'il modo in cui otteniamo l'istanza del mapper Gson, usando un oggetto factory, GsonBuilder, un modo comune di usare lo GSON è qui.

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

Per uso tipo primitivo di sotto di un

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

Godetevi il JSON analisi!

+1

Grazie! Se ho capito bene, ogni volta che provo a deserializzare con questo set 'BooleanTypeAdapter', qualsiasi' boolean' sarà trattato in questo modo? – Eliezer

+0

@Maheshwar Ligade Quindi, per quanto riguarda la domanda ** campi specifici ** parte? Questa soluzione non funziona per le risposte contengono il valore intero normale come 'quantity: 0' questa chiave non può essere rappresentata come' Boolean' –

0

Se sto capendo correttamente, vuoi normalizzare o massaggiare il valore sul JSONReader in arrivo da un int a qualcos'altro, come un booleano.

In tal caso, probabilmente si desidera creare una classe adattatore che estenda TypeAdapter <YourFieldNameType> e sovrascriva read(). Si ottiene il valore da nextInt() e quindi si restituisce il valore booleano appropriato in base al suo valore. Potrebbe essere necessario verificare i valori nulli, a seconda della configurazione del parser.

Se è necessario, è possibile sovrascrivere write() nella stessa classe dell'adattatore per forzare i booleani nel codice client in numeri interi per JsonWriter.

[EDIT]

Per riferimento, ecco un esempio del mio TypeAdapter, che converte un "Comandi" classe enum a/da un numero intero.

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()); 
    } 

} 

adatta questa sostanza op entrata e in uscita sul "CommandName" param serializzato rappresentata localmente come un'enumerazione "Comandi" e come numero intero da remoto. Tutto ciò che ha a che fare con questo comando enum viene filtrato attraverso questa classe dell'adattatore che sovrascrive read() e write(). Alla fine questo porta un peer WebSocket, ma niente di tutto questo è importante ai fini di questa discussione. HTH.

+0

Diciamo che ci sono alcuni valori interi che voglio trattare come booleano, e alcuni che voglio trattare come numeri interi, come ho affermato nell'ultima frase della domanda. – Eliezer

+0

Se provengono dallo stesso campo serializzato su JsonReader, è necessario inserire una logica aggiuntiva in read() per prendere una decisione e restituire la cosa giusta.Ma, in poche parole, se devi modificare i tipi in entrata o in uscita con un altro tipo, devi creare una classe TypeAdapter per questi tipi. – jdv

+0

Ho aggiornato la domanda per spiegare il problema un po 'più chiaramente. – Eliezer

Problemi correlati