[英]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.