我需要编写一个使用socket与服务器通信的客户端。消息协议采用json格式。服务器将按需将多个json块推送到客户端。 消息是这样的:
{"a": 1, "b": { "c": 1}}{"a": 1, "b": { "c": 1}}...
您可以看到json块之间没有分隔符或标识符。
我能找到的json解析器(如fastjson,jackson)都只能将流作为整个json块处理,甚至是它们提供的流api。当我使用这些api来解析流时,它们会在第一个json块的末尾抛出异常,表示下一个令牌" {"无效。
java中是否有json解析器可以处理我的问题?还是有其他方法可以解决这个问题?
答案 0 :(得分:0)
您可以使用Genson执行此操作。 首先将其配置为允许" permissive"解析然后反序列化迭代器中的值。当你在迭代器上调用next时,Genson将逐个解析对象。因此,您可以通过这种方式解析非常大的输入。
Genson genson = new GensonBuilder().usePermissiveParsing(true).create();
ObjectReader reader = genson.createReader(inputStream);
Iterator<SomeObject> iterator = genson.deserializeValues(reader, GenericType.of(SomeObject.class));
这部分API有点冗长,因为用例并不常见。
UPDATE 在Genson 1.4中,usePermissiveParsing已被删除,有利于默认接受未包含在数组中的根值。见https://github.com/owlike/genson/issues/78
答案 1 :(得分:0)
最后,根据我的情况,它不会在java中找到JSON解析器。 我正在使用netty来构建网络应用程序。对于nio,当有来自网络的数据时,调用ByteToMessageDecoder中的解码方法。 在这个方法中,我需要从ByteBuf中找出JSON块。
由于没有可用的JSON解析器,我编写了一个从ByteBuf中拆分JSON块的方法。
public static void extractJsonBlocks(ByteBuf buf, List<Object> out) throws UnsupportedEncodingException {
// the total bytes that can read from ByteBuf
int readable = buf.readableBytes();
int bracketDepth = 0;
// when found a json block, this value will be set
int offset = 0;
// whether current character is in a string value
boolean inStr = false;
// a temporary bytes buf for store json block
byte[] data = new byte[readable];
// loop all the coming data
for (int i = 0; i < readable; i++) {
// read from ByteBuf
byte b = buf.readByte();
// put it in the buffer, be care of the offset
data[i - offset] = b;
if (b == SYM_L_BRACKET && !inStr) {
// if it a left bracket and not in a string value
bracketDepth++;
} else if (b == SYM_R_BRACKET && !inStr) {
// if it a right bracket and not in a string value
if (bracketDepth == 1) {
// if current bracket depth is 1, means found a whole json block
out.add(new String(data, "utf-8").trim());
// create a new buffer
data = new byte[readable - offset];
// update the offset
offset = i;
// reset the bracket depth
bracketDepth = 0;
} else {
bracketDepth--;
}
} else if (b == SYM_QUOTE) {
// when find a quote, we need see whether preview character is escape.
byte prev = i == 0 ? 0 : data[i - 1 - offset];
if (prev != SYM_ESCAPE) {
inStr = !inStr;
}
}
}
// finally there may still be some data left in the ByteBuf, that can not form a json block, they should be used to combine with the following datas
// so we need to reset the reader index to the first byte of the left data
// and discard the data used for json blocks
buf.readerIndex(offset == 0 ? offset : offset + 1);
buf.discardReadBytes();
}
也许这是一个不完美的解析器,但它现在适用于我的应用程序。