Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting JSON between string and byte[] with GSON

I'm using hibernate to map objects to the database. A client (an iOS app) sends me particular objects in JSON format which I convert to their true representation using the following utility method:

/**
     * Convert any json string to a relevant object type
     * @param jsonString the string to convert
     * @param classType the class to convert it too
     * @return the Object created
     */
    public static <T> T getObjectFromJSONString(String jsonString, Class<T> classType) {
        
        if(stringEmptyOrNull(jsonString) || classType == null){
            throw new IllegalArgumentException("Cannot convert null or empty json to object");
        }

        try(Reader reader = new StringReader(jsonString)){
            Gson gson = new GsonBuilder().create();
            return gson.fromJson(reader, classType);
        } catch (IOException e) {
            Logger.error("Unable to close the reader when getting object as string", e);
        }
        return null;
    }

The issue however is, that in my pogo I store the value as a byte[] as can be seen below (as this is what is stored in the database - a blob):

@Entity
@Table(name = "PersonalCard")
public class PersonalCard implements Card{
    
    @Id @GeneratedValue
    @Column(name = "id")
    private int id;
    
    @OneToOne
    @JoinColumn(name="userid")
    private int userid;
    
    @Column(name = "homephonenumber")
    protected String homeContactNumber;
    
    @Column(name = "mobilephonenumber")
    protected String mobileContactNumber;
    
    @Column(name = "photo")
    private byte[] optionalImage;
    
    @Column(name = "address")
    private String address;

Now of course, the conversion fails because it can't convert between a byte[] and a String.

Is the best approach here to change the constructor to accept a String instead of a byte array and then do the conversion myself whilst setting the byte array value or is there a better approach to doing this.

The error thrown is as follows;

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 96 path $.optionalImage

Thanks.

Edit In fact even the approach I suggested will not work due to the way in which GSON generates the object.

like image 627
Biscuit128 Avatar asked Aug 27 '14 08:08

Biscuit128


People also ask

How do you convert a byte array into a string?

There are two ways to convert byte array to String: By using String class constructor. By using UTF-8 encoding.

Can you put byte array in JSON?

JSON does not support that. Use Base64. That is your library supporting it, not JSON itself. The byte array wont be stored as byte array in the JSON, JSON is a text format meant to be human readable.

Does GSON offer parse () function?

The GSON JsonParser class can parse a JSON string or stream into a tree structure of Java objects. GSON also has two other parsers. The Gson JSON parser which can parse JSON into Java objects, and the JsonReader which can parse a JSON string or stream into tokens (a pull parser).


2 Answers

You can use this adapter to serialize and deserialize byte arrays in base64. Here's the content.

   public static final Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class,
            new ByteArrayToBase64TypeAdapter()).create();

    // Using Android's base64 libraries. This can be replaced with any base64 library.
    private static class ByteArrayToBase64TypeAdapter implements JsonSerializer<byte[]>, JsonDeserializer<byte[]> {
        public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            return Base64.decode(json.getAsString(), Base64.NO_WRAP);
        }

        public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(Base64.encodeToString(src, Base64.NO_WRAP));
        }
    }

Credit to the author Ori Peleg.

like image 133
Ken de Guzman Avatar answered Oct 05 '22 20:10

Ken de Guzman


From some blog for future reference, incase the link is not available, atleast users can refer here.

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.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

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

public class GsonHelper {
    public static final Gson customGson = new GsonBuilder()
            .registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
                @Override
                public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                return new Date(json.getAsLong());
                }
            })
            .registerTypeHierarchyAdapter(byte[].class,
                    new ByteArrayToBase64TypeAdapter()).create();

    // Using Android's base64 libraries. This can be replaced with any base64 library.
    private static class ByteArrayToBase64TypeAdapter implements JsonSerializer<byte[]>, JsonDeserializer<byte[]> {
        public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            return Base64.decode(json.getAsString(), Base64.NO_WRAP);
        }

        public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(Base64.encodeToString(src, Base64.NO_WRAP));
        }
    }
}
like image 31
Ankur Singhal Avatar answered Oct 05 '22 22:10

Ankur Singhal