Java 使用GSON在字符串和字节[]之间转换JSON

Java 使用GSON在字符串和字节[]之间转换JSON,java,arrays,json,hibernate,gson,Java,Arrays,Json,Hibernate,Gson,我正在使用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 t

我正在使用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;
    }
当然,现在转换失败了,因为它无法在字节[]和字符串之间转换

在这里,最好的方法是将构造函数更改为接受字符串而不是字节数组,然后在设置字节数组值时自己进行转换,还是有更好的方法进行转换

抛出的错误如下所示

com.google.gson.JsonSyntaxException:java.lang.IllegalStateException: 应为BEGIN_数组,但在第1行第96列路径处为字符串 $.optionImage

谢谢

编辑事实上,由于GSON生成对象的方式,即使是我建议的方法也不起作用。

您可以使用它来序列化和反序列化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));
        }
    }
public static final Gson customGson=new GsonBuilder().registerTypeHierarchyAdapter(字节[].class,
新建ByteArrayToBase64TypeAdapter()).create();
//使用Android的base64库。这可以替换为任何base64库。
私有静态类ByteArrayToBase64TypeAdapter实现JsonSerializer、JsonDeserializer{
公共字节[]反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext)引发JsonParseException{
返回Base64.decode(json.getAsString(),Base64.NO_WRAP);
}
公共JsonElement序列化(字节[]src,类型typeOfSrc,JsonSerializationContext){
返回新的JsonPrimitive(Base64.encodeToString(src,Base64.NO_WRAP));
}
}

作者的功劳

如果链接不可用,至少用户可以在此处参考。

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));
        }
    }
}
import com.google.gson.gson;
导入com.google.gson.GsonBuilder;
导入com.google.gson.JsonDeserializationContext;
导入com.google.gson.JsonDeserializer;
导入com.google.gson.JsonElement;
导入com.google.gson.JsonParseException;
导入com.google.gson.JsonPrimitive;
导入com.google.gson.JsonSerializationContext;
导入com.google.gson.JsonSerializer;
导入java.lang.reflect.Type;
导入java.util.Date;
公共类GsonHelper{
public static final Gson customGson=new GsonBuilder()
.registerTypeAdapter(Date.class,新的JsonDeserializer(){
@凌驾
公共日期反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext)引发JsonParseException{
返回新日期(json.getAsLong());
}
})
.registerTypeHierarchyAdapter(字节[]。类,
新建ByteArrayToBase64TypeAdapter()).create();
//使用Android的base64库。这可以被任何base64库取代。
私有静态类ByteArrayToBase64TypeAdapter实现JsonSerializer、JsonDeserializer{
公共字节[]反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext)引发JsonParseException{
返回Base64.decode(json.getAsString(),Base64.NO_WRAP);
}
公共JsonElement序列化(字节[]src,类型typeOfSrc,JsonSerializationContext){
返回新的JsonPrimitive(Base64.encodeToString(src,Base64.NO_WRAP));
}
}
}

您只需在POJO中将照片作为字符串,在Setter方法中将字符串转换为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();
    }
}

我需要一个解决方案来符合字符串类型的格式字节必须保存base64编码值的状态。POJO保存字节[],JSON对象具有字符串属性

在我的例子中,我不能使用android库进行base64处理,因为在后端应用程序中使用了Gson序列化。因此,我使用java提供的java.util.Base64

与基于JsonSerializer的适配器不同,我使用了JsonDeserializer接口TypeAdapteradapter。有了它,我可以覆盖Gson的HTML转义功能,以防止在base64编码中转义填充字符“=”。如果不这样做,“hello World”的编码值将是“aGVsbG8gV29ybGQ\u003d”,而不是“aGVsbG8gV29ybGQ=”,另一端的反序列化程序将失败

以下是自定义适配器的代码:

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);
    }
  }
}
公共类ByteArrayAdapter扩展了TypeAdapter{
@凌驾
public void write(JsonWriter out,byte[]byteValue)抛出IOException{
布尔值oldtmlsafe=out.isHtmlSafe();
试一试{
out.setHtmlSafe(false);
out.value(新字符串(Base64.getEncoder().encode(byteValue));
}最后{
out.setHtmlSafe(oldHtmlSafe);
}
}
@凌驾
公共字节[]已读(JsonReader in){
试一试{
if(in.peek()==JsonToken.NULL){
in.nextNull();
返回新字节[]{};
}
字符串byteValue=in.nextString();
if(字节值!=null){
返回Base64.getDecoder().decode(字节值);
}
返回新字节[]{};
}捕获(例外e){
抛出新的JsonParseException(e);
}
}
}

问题出在哪里?您不能使用json格式序列化/反序列化字节数组吗?或者什么?我接收一个json对象,并直接将其转换为hibernate pojo。hibernate pojo以字节数组格式工作。GSON库将字符串转换为对象,但似乎无法转换字节[]失败的原因是什么?已添加到OPM中可能这可以帮助您我有一个HashMap-它似乎无法与适配器toJson一起正常工作-我获取Java对象引用,而不是目标base64值。有什么想法吗?我们不应该这样做。
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);
    }
  }
}