与此同时,虽然您的服务器代码尚未修复,但出于“教育”目的,我可以提供一个示例,让字节编码的响应适应您可以解析的内容,以避免将来出现不良做法(请不要'不要执行以下操作)。
解决您的问题的想法是调整传入的有效负载(字节数组编码的文本)到可以作为 JSON 使用的字节/字符流。
使用 org.json 可能这样实现(但是,我不确定我是否正确实现了它):
public final class Decoding {
private Decoding() {
}
public static Reader of(final Reader reader) {
final JSONTokener jsonTokener = new JSONTokener(reader);
return new Reader() {
private boolean beginToProcess = true;
private boolean endToProcess = true;
@Override
public int read(@Nonnull final char[] buffer, final int offset, final int length)
throws IOException {
if ( beginToProcess ) {
final char ch = jsonTokener.nextClean();
if ( ch != '[' ) {
throw new IOException("Not an array begin: " + ch);
}
beginToProcess = false;
}
if ( !jsonTokener.more() ) {
if ( endToProcess ) {
final char ch = jsonTokener.nextClean();
if ( ch != '\u0000' ) {
throw new IOException("Not an array or document end: " + ch);
}
endToProcess = false;
}
return -1;
}
final char b = (char) (int) jsonTokener.nextValue();
if ( jsonTokener.more() ) {
final char ch = jsonTokener.nextClean();
switch ( ch ) {
case ',':
case ']':
// do nothing
break;
default:
throw new IOException("Not an array delimiter: " + ch);
}
}
buffer[offset] = b;
return 1;
}
@Override
public void close()
throws IOException {
reader.close();
}
};
}
...
或以 Gson 为例:
...
public static Reader of(final JsonReader jsonReader) {
return new Reader() {
private boolean beginToProcess = true;
private boolean endToProcess = true;
@Override
public int read(@Nonnull final char[] buffer, final int offset, final int length)
throws IOException {
if ( beginToProcess ) {
jsonReader.beginArray();
beginToProcess = false;
}
if ( !jsonReader.hasNext() ) {
if ( endToProcess ) {
jsonReader.endArray();
endToProcess = false;
}
return -1;
}
final int b = jsonReader.nextInt();
buffer[offset] = (char) b;
return 1;
}
@Override
public void close()
throws IOException {
jsonReader.close();
}
};
}
}
这两种解码器都不是最理想的,不能提供最佳性能,但我希望你的服务器修复后就不需要它了。现在您可以解码输入阅读器并将它们转换为有效的 JSON 文档(在 JUnit 5 测试中):
public final class DecodingTest {
@Test
public void test()
throws IOException {
final String payload = "[123,34,97,117,116,104,111,114,34,58,34,65,110,116,111,110,34,44,34,116,121,112,101,34,58,34,115,101,114,118,101,114,32,105,110,102,111,34,44,34,100,97,116,101,34,58,34,48,56,47,48,49,47,50,48,50,49,34,44,34,99,111,110,116,101,110,116,34,58,34,34,44,34,111,112,116,34,58,123,34,99,112,117,34,58,123,34,102,114,101,113,34,58,91,51,56,54,54,46,48,52,49,56,55,53,44,49,54,48,48,44,51,57,48,48,93,44,34,117,115,97,103,101,34,58,91,48,44,48,44,49,44,50,44,49,44,49,44,48,44,50,93,44,34,108,111,97,100,34,58,91,48,46,53,44,48,46,54,51,44,48,46,54,49,93,125,44,34,109,101,109,111,114,121,34,58,123,34,114,97,109,34,58,91,49,53,46,53,52,44,49,50,46,48,49,44,50,50,46,55,44,50,46,56,53,44,57,46,54,55,93,125,44,34,100,105,115,107,115,34,58,123,34,115,115,100,34,58,91,50,49,57,46,49,44,49,51,44,49,57,52,46,57,44,54,46,51,93,44,34,104,100,100,34,58,91,48,44,48,44,48,44,49,48,48,93,125,44,34,116,101,109,112,115,34,58,123,34,99,111,114,101,45,48,34,58,91,51,50,44,56,53,44,49,48,53,93,44,34,99,111,114,101,45,49,34,58,91,51,54,44,56,53,44,49,48,53,93,44,34,99,111,114,101,45,50,34,58,91,51,55,44,56,53,44,49,48,53,93,44,34,99,111,114,101,45,51,34,58,91,51,56,44,56,53,44,49,48,53,93,125,125,44,34,97,116,116,97,99,104,101,100,34,58,110,117,108,108,125]";
final String expected = "{\"author\":\"Anton\",\"type\":\"server info\",\"date\":\"08/01/2021\",\"content\":\"\",\"opt\":{\"cpu\":{\"freq\":[3866.041875,1600,3900],\"usage\":[0,0,1,2,1,1,0,2],\"load\":[0.5,0.63,0.61]},\"memory\":{\"ram\":[15.54,12.01,22.7,2.85,9.67]},\"disks\":{\"ssd\":[219.1,13,194.9,6.3],\"hdd\":[0,0,0,100]},\"temps\":{\"core-0\":[32,85,105],\"core-1\":[36,85,105],\"core-2\":[37,85,105],\"core-3\":[38,85,105]}},\"attached\":null}";
try ( final Reader reader = Decoding.of(new StringReader(payload));
final Writer writer = new StringWriter() ) {
CharStreams.copy(reader, writer);
Assertions.assertEquals(expected, writer.toString());
}
try ( final Reader reader = Decoding.of(new JsonReader(new StringReader(payload)));
final Writer writer = new StringWriter() ) {
CharStreams.copy(reader, writer);
Assertions.assertEquals(expected, writer.toString());
}
}
}
请注意,CharStreams.copy 为简洁起见取自 Google Guava。
现在可以将阅读器作为常规 JSON 文档被库、org.json、Gson、Jackson、Moshi 或其他任何东西使用。