Issue
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.
Solution
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.
Answered By - Ken de Guzman