使用 GSON 在字符串和字节 [] 之间转换 JSON
Posted
技术标签:
【中文标题】使用 GSON 在字符串和字节 [] 之间转换 JSON【英文标题】:Converting JSON between string and byte[] with GSON 【发布时间】:2014-10-20 18:03:04 【问题描述】:我正在使用休眠将对象映射到数据库。客户端(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 之间进行转换。
这里最好的方法是改变构造函数以接受字符串而不是字节数组,然后在设置字节数组值的同时自己进行转换,还是有更好的方法来做到这一点。
抛出的错误如下;
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 预期为 BEGIN_ARRAY,但在第 1 行第 96 列路径为 STRING $.optionalImage
谢谢。
编辑事实上,由于 GSON 生成对象的方式,即使我建议的方法也行不通。
【问题讨论】:
有什么问题?您不能使用 json 格式序列化/反序列化字节数组吗?还是什么? 我正在接收一个 json 对象并将其直接转换为我的休眠 pojo。 hibernate pojo 以字节数组格式工作。 GSON 库将字符串转换为对象,似乎无法转换字节 [] 失败的错误是什么? 已添加到 OP 也许这可以帮助你link 【参考方案1】:这对我有用:
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
.registerTypeAdapter(byte[].class, (JsonSerializer<byte[]>) (src, typeOfSrc, context) -> new JsonPrimitive(new String(src)))
.registerTypeAdapter(byte[].class, (JsonDeserializer<byte[]>) (json, typeOfT, context) -> json == null ? null : json.getAsString() == null ? null : json.getAsString().getBytes())
.create();
【讨论】:
【参考方案2】:我需要符合OpenAPI specification 的解决方案,该OpenAPI specification 声明格式字节的字符串类型必须保存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);
【讨论】:
【参考方案3】:你可以在 POJO 中简单地将照片作为 String ,在 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();
【讨论】:
我们不应该这样做。【参考方案4】:来自一些博客以备将来参考,如果链接不可用,至少用户可以参考这里。
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));
【讨论】:
【参考方案5】:您可以使用此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。
【讨论】:
我有一个 HashMap以上是关于使用 GSON 在字符串和字节 [] 之间转换 JSON的主要内容,如果未能解决你的问题,请参考以下文章
使用Google的Gson实现对象和json字符串之间的转换