Java 使用GSON和Hibernate存储任意数据
我想保留一些只与客户端相关的数据。我喜欢故意忽略数据库规范化,因为数据在服务器端非常无用 我可以通过让客户机将数据转换为JSON并在请求中发送的JSON中包含字符串来完成这一点。然而,我更喜欢更干净更优雅的解决方案 我想要的是: 给定 和一个输入Java 使用GSON和Hibernate存储任意数据,java,json,hibernate,gson,Java,Json,Hibernate,Gson,我想保留一些只与客户端相关的数据。我喜欢故意忽略数据库规范化,因为数据在服务器端非常无用 我可以通过让客户机将数据转换为JSON并在请求中发送的JSON中包含字符串来完成这一点。然而,我更喜欢更干净更优雅的解决方案 我想要的是: 给定 和一个输入 { someString: "The answer", someInt: 43, clientData: { x: [1, 1, 2, 3, 5, 8, 13], y: [1,
{
someString: "The answer",
someInt: 43,
clientData: {
x: [1, 1, 2, 3, 5, 8, 13],
y: [1, 1, 2, 6, 24, 120],
tonsOfComplicatedStuff: {stuff: stuff}
}
}
将压缩为JSON的
clientData
存储在一列中。注意,我不想为MyEntity编写适配器,因为有很多列。我需要一个单列适配器。列类型不必是字符串(Serializable
或其他任何东西,因为服务器根本不在乎)。Gson支持@JsonAdapter
注释,允许指定JSON(反)序列化器、类型适配器,甚至类型适配器工厂。而且该注释看起来是注释MyEntity
中的clientData
字段的一个很好的候选者:
最终类MyEntity{
字符串;字符串;
int-someInt;
@高球
@JsonAdapter(PackedJsonTypeAdapterFactory.class)
字符串clientData;
}
类型适配器工厂可能如下所示:
最终类包djsonTypeAdapterFactory
实现TypeAdapterFactory{
//Gson可以自己实例化它
私有包djsonTypeAdapterFactory(){
}
@凌驾
公共类型适配器创建(最终Gson Gson、最终TypeToken TypeToken){
@抑制警告(“未选中”)
最终类型适配器TypeAdapter=(TypeAdapter)新的PackedJsonTypeAdapter(gson);
返回类型适配器;
}
私有静态最终类PackedJsonTypeAdapter
扩展类型适配器{
私人最终Gson Gson;
专用PackedJsonTypeAdapter(最终Gson Gson){
this.gson=gson;
}
@凌驾
public void write(最终JsonWriter out,最终字符串json){
最终的JsonElement=gson.fromJson(json,JsonElement.class);
toJson(jsonElement,out);
}
@凌驾
公共字符串读取(中的最终JsonReader){
final JsonElement JsonElement=gson.fromJson(in,JsonElement.class);
返回jsonElement!=null?jsonElement.toString():null;
}
}
}
请注意,此转换器策略是作为类型适配器工厂实现的,因为这是访问我所知的Gson
实例的唯一方法,而且JsonSerializer
/JsonDeserializer
似乎无法通过序列化上下文进行良好的解析。这里的另一个陷阱是,这个实现是基于树的,需要将JSON树完全存储在内存中。理论上,可以有一个很好的面向流的实现,比如说gson.fromJson(jsonReader)->jsonReader
,或者一个jsonReader
->Reader
装饰器被重定向到StringWriter
,但我很长一段时间都找不到任何替代方案
publicstaticvoidmain(最终字符串…args){
最终Gson Gson=新Gson();
out.println(“反序列化:”);
最后一个字符串incomingJson=“{someString:\'theanswer\”,somesint:43,clientData:{x:[1,1,2,3,5,8,13],y:[1,1,2,6,24120],tonsoffomplexeddstuff:{stuff:stuff}”;
final MyEntity MyEntity=gson.fromJson(incomingJson,MyEntity.class);
out.println(“\t”+myEntity.someString);
out.println(“\t”+myEntity.someInt);
out.println(“\t”+myEntity.clientData);
out.println(“序列化:”);
最终字符串outgoingJson=gson.toJson(myEntity);
out.println(“\t”+outgoingJson);
out.println(“相等检查”);
out.println(“\t”+areEqual(gson,incomingJson,outgoingJson));
}
私有静态布尔值areEqual(最终Gson Gson、最终字符串incomingJson、最终字符串outgoingJson){
final JsonElement incoming=gson.fromJson(incomingJson,JsonElement.class);
final JsonElement outgoing=gson.fromJson(outgoingJson,JsonElement.class);
返回传入。等于(传出);
}
输出:
deserialization:
The answer
43
{"x":[1,1,2,3,5,8,13],"y":[1,1,2,6,24,120],"tonsOfComplicatedStuff":{"stuff":"stuff"}}
serialization:
{"someString":"The answer","someInt":43,"clientData":{"x":[1,1,2,3,5,8,13],"y":[1,1,2,6,24,120],"tonsOfComplicatedStuff":{"stuff":"stuff"}}}
equality check:
true
不过,我不知道它是否能很好地与Hibernate配合使用
编辑 尽管JSON压缩字符串被收集到内存中,但由于各种原因,流式传输可能更便宜,并且可以节省一些内存。流式传输的另一个优点是,这样的JSON打包类型适配器不再需要类型适配器工厂,
Gson
实例因此保持JSON流的原样,但是仍然进行一些规范化,如{stuff:stuff}
->{“stuff”:“stuff”}
。例如:
@JsonAdapter(PackedJsonStreamTypeAdapter.class)
字符串clientData;
final class PackedJsonStreamTypeAdapter
扩展类型适配器{
私有PackedJsonStreamTypeAdapter(){
}
@凌驾
public void write(最终JsonWriter out,最终字符串json)
抛出IOException{
@抑制警告(“资源”)
最终读取器=新的StringReader(json);
writeNormalizedJsonStream(新JsonReader(reader),输出);
}
@凌驾
公共字符串读取(中的最终JsonReader)
抛出IOException{
@抑制警告(“资源”)
最终编写器=新的StringWriter();
writeNormalizedJsonStream(in,新JsonWriter(writer));
返回writer.toString();
}
}
final类JsonStreams{
私有JsonStreams(){
}
静态void writernomalizedjsonstream(最终JsonReader读取器,最终JsonWriter写入器)
抛出IOException{
writeNormalizedJsonStream(读者、作者、真实);
}
@抑制警告(“资源”)
静态void writernomalizedjsonstream(最终JsonReader读取器、最终JsonWriter写入器、最终布尔isLenient)
抛出IOException{
智力水平=0;
for(JsonToken-token=reader.peek();
deserialization:
The answer
43
{"x":[1,1,2,3,5,8,13],"y":[1,1,2,6,24,120],"tonsOfComplicatedStuff":{"stuff":"stuff"}}
serialization:
{"someString":"The answer","someInt":43,"clientData":{"x":[1,1,2,3,5,8,13],"y":[1,1,2,6,24,120],"tonsOfComplicatedStuff":{"stuff":"stuff"}}}
equality check:
true