我正在使用hibernate将对象映射到数据库。客户端(iOS应用程序)以JSON格式向我发送特定对象,我使用以下实用方法将其转换为真实表示
/**
* 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;
}
然而问题是,在我的pogo中,我将值存储为byte [],如下所示(因为这是存储在数据库中的内容 - 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;
当然,转换失败,因为它无法在byte []和String之间进行转换。
这里最好的方法是将构造函数更改为接受String而不是字节数组,然后在设置字节数组值时自己进行转换,或者有更好的方法来执行此操作。
抛出的错误如下;
com.google.gson.JsonSyntaxException:java.lang.IllegalStateException: 预期BEGIN_ARRAY但是在第1行第96列路径处是STRING $ .optionalImage
由于
编辑事实上,由于GSON生成对象的方式,我建议的方法也行不通。
答案 0 :(得分:18)
您可以使用此adapter来序列化和反序列化base64中的字节数组。 这是内容。
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));
}
}
归功于作者Ori Peleg。
答案 1 :(得分:2)
来自某个博客以供将来参考,如果该链接不可用,至少用户可以参考此处。
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));
}
}
}
答案 2 :(得分:0)
您可以简单地将照片作为字符串在POJO中,并在Setter方法中将String转换为byte []并在Getter方法中返回byte []
@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;
@Column
byte[] optionalImage;
public byte[] getOptionalImage()
{
return optionalImage;
}
public void setOptionalImage(String s)
{
this.optionalImage= s.getBytes();
}
}
答案 3 :(得分:0)
我需要解决方案来符合 OpenAPI specification 的规定,即格式字节的 String 类型必须保存 base64 编码值。 POJO 持有 byte[] 并且 JSON 对象拥有 String 属性。
就我而言,我无法使用 android 库进行 base64 处理,因为后端应用程序中使用了 Gson 序列化。出于这个原因,我使用了 java 提供的 java.util.Base64 类。
我使用了 TypeAdapter 以下是自定义适配器的代码:public class ByteArrayAdapter extends TypeAdapter<byte[]> {
@Override
public void write(JsonWriter out, byte[] byteValue) throws IOException {
boolean oldHtmlSafe = out.isHtmlSafe();
try {
out.setHtmlSafe(false);
out.value(new String(Base64.getEncoder().encode(byteValue)));
} finally {
out.setHtmlSafe(oldHtmlSafe);
}
}
@Override
public byte[] read(JsonReader in) {
try {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return new byte[]{};
}
String byteValue = in.nextString();
if (byteValue != null) {
return Base64.getDecoder().decode(byteValue);
}
return new byte[]{};
} catch (Exception e) {
throw new JsonParseException(e);
}
}
}