[英]Serializing Object to Json
我正在尝试使用Gson来获取一些Java Object并将其序列化为json并获取表示该Json的字节数组。 我需要一个字节数组,因为我将输出传递给需要它为字节数组的外部依赖项。
public byte[] serialize(Object object){
return gson.toJson(object).getBytes();
}
我有两个问题:
String
然后转换为byte[]
可能会带来一些不必要的开销。 是否有更优化的方法来获取byte[]
? 编辑:我对第1点的回答是错误的。
2)如果您仅使用普通gson转换器,则会有很多不必要的反射开销。 在您的情况下,编写自定义适配器将极大地提高性能。 这是一篇关于该内容的更多信息的文章https://open.blogs.nytimes.com/2016/02/11/improving-startup-time-in-the-nytimes-android-app/?_r=0
如果输入是String,则gson似乎会按原样返回String。 它不对输入进行任何验证。 这是预期的吗?
是的,这很好。 它只是返回给定字符串的JSON字符串表示形式。
我想以一种可以验证输入对象实际上是Json的方式使用Gson。 我该怎么办?
本身就不需要。 Gson.toJson()
方法接受要序列化的对象,并始终生成有效的JSON。 如果您要进行反序列化,则Gson会在读取/解析/反序列化过程中对无效的JSON文档进行快速失败(实际上是读取,这是Gson的最底层)。
我要在短时间内调用该序列化函数数千次。 转换为String然后转换为byte []可能会带来一些不必要的开销。 是否有更优化的方法来获取byte []?
是的,仅为了公开其内部char[]
克隆而累积JSON字符串会浪费内存。 Gson基本上是一种面向流的工具,请注意,有一些Gson.toJson
方法重载接受了Appendable
,而这些重载基本上是Gson核心(只是快速了解Gson.fromJson(Object)
工作方式-它只是创建一个StringWriter
实例由于Appendable
接口而累积了一个字符串)。 如果Gson可以通过Reader
而不是写入Appendable
发出JSON令牌,那将非常酷,但是很遗憾,这个想法被拒绝了,很可能永远不会在Gson中实现。 由于Gson在反序列化期间不会以读取语义的方式(从您的代码角度)发出JSON令牌,因此您必须缓冲整个结果:
private static byte[] serializeToBytes(final Object object)
throws IOException {
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final OutputStreamWriter writer = new OutputStreamWriter(outputStream);
gson.toJson(object, writer);
writer.flush();
return outputStream.toByteArray();
}
这个不使用StringWriter
因此不会累积带有克隆数组ping-pong的中间字符串。 我不知道是否有可以利用/重用现有字节数组的编写器/输出流,但是我相信应该有一些,因为它为您在问题中提到的性能目的提供了很好的理由。
如果可能的话,您还可以检查库接口/ API是否以某种方式公开/接受OutputStream
那么您可以轻松地将此类输出流传递给serializeToBytes
方法,甚至删除该方法。 如果它可以使用输入流,而不仅仅是字节数组,那么您还可以看一下将输出流转换为输入流,以便serializeToBytes
方法可以返回InputStream
或Reader
(需要一些开销,但可以处理无限数据-找到余额):
private static InputStream serializeToByteStream(final Object object)
throws IOException {
final PipedInputStream inputStream = new PipedInputStream();
final OutputStream outputStream = new PipedOutputStream(inputStream);
new Thread(() -> {
try {
final OutputStreamWriter writer = new OutputStreamWriter(outputStream);
gson.toJson(object, writer);
writer.flush();
} catch ( final IOException ex ) {
throw new RuntimeException(ex);
} finally {
try {
outputStream.close();
} catch ( final IOException ex ) {
throw new RuntimeException(ex);
}
}
}).start();
return inputStream;
}
使用示例:
final String value = "foo";
System.out.println(Arrays.toString(serializeToBytes(value)));
try ( final InputStream inputStream = serializeToByteStream(value) ) {
int b;
while ( (b = inputStream.read()) != -1 ) {
System.out.print(b);
System.out.print(' ');
}
System.out.println();
}
输出:
[34,102,111,111,34]
34102111111 34
两者都代表一个ASCII码数组,从字面上表示一个字符串"foo"
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.