JsonParseException:无效的 UTF-8 中间字节 0x2d
JsonParseException: Invalid UTF-8 middle byte 0x2d
我有一个 JSON 字符串,我正在从中制作一个 InputStream object
,如下所示,然后我正在制作一个 GenericRecord
对象,因为我正在尝试序列化我的 JSON 反对 Avro 模式。
InputStream input = new ByteArrayInputStream(jsonString.getBytes());
DataInputStream din = new DataInputStream(input);
Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din);
DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema);
// below line is throwing exception
GenericRecord datum = reader.read(null, decoder);
下面是我得到的异常:
org.codehaus.jackson.JsonParseException: Invalid UTF-8 middle byte 0x2d at [Source: java.io.DataInputStream@562aee31; line: 1, column: 74]
这是发生此异常的实际 JSON 字符串:
{"name":"car_test","attr_value":"2006|Renault|Megane II Coupé-Cabriolet|null|null|null|null|0|Wed Feb 03 10:00:59 GMT-07:00 2016|1|77|null|null|null|null","data_id":900}
我做了一些研究,发现我需要使用 ByteArrayInputStream
和 UTF-8 编码,如下所示:
InputStream input = new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8.displayName()));
但是我的问题是这个异常的原因是什么?为什么它会发生在我上面的 JSON 字符串上?我只是想了解为什么在我上面的 JSON 字符串上会发生此异常。使用 UTF-8
是正确的解决方法吗?
这个错误是什么意思Invalid UTF-8 middle byte 0x2d
?
您从 Java Unicode 字符串 jsonString
开始。
然后使用 String.getBytes()
将其转换为字节流。由于您没有指定字节编码,因此使用的平台默认值很可能是 ISO 8859-1。
现在您从 (Data)InputStream
解析 JSON。现在 Avro 似乎使用 UTF-8 来解码字节。当它遇到 é
(0x2d) 时失败,因为它不是有效的 UTF 字节序列。
所以最后是实际编码(ISO 8859-1)和预期编码(UTF-8)不匹配。
你可以像以前一样解决这个问题,或者只是避免从字符串到字节:
Decoder decoder = DecoderFactory.get().jsonDecoder(schema, jsonString);
您可能对使用 Jackson Avro 模块的更方便的方法感兴趣,而不是使用低级 Avro 解码器功能:
https://github.com/FasterXML/jackson-dataformat-avro/issues
您可以在其中提供 Avro Schema,但仍可使用 POJO。
您还可以对 JSON 部分使用常规 JSON Jackson 数据绑定(不同的 ObjectMapper
),并将 JSON 读入 POJO,将 POJO 写入 Avro(或其他组合)。
我有一个 JSON 字符串,我正在从中制作一个 InputStream object
,如下所示,然后我正在制作一个 GenericRecord
对象,因为我正在尝试序列化我的 JSON 反对 Avro 模式。
InputStream input = new ByteArrayInputStream(jsonString.getBytes());
DataInputStream din = new DataInputStream(input);
Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din);
DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema);
// below line is throwing exception
GenericRecord datum = reader.read(null, decoder);
下面是我得到的异常:
org.codehaus.jackson.JsonParseException: Invalid UTF-8 middle byte 0x2d at [Source: java.io.DataInputStream@562aee31; line: 1, column: 74]
这是发生此异常的实际 JSON 字符串:
{"name":"car_test","attr_value":"2006|Renault|Megane II Coupé-Cabriolet|null|null|null|null|0|Wed Feb 03 10:00:59 GMT-07:00 2016|1|77|null|null|null|null","data_id":900}
我做了一些研究,发现我需要使用 ByteArrayInputStream
和 UTF-8 编码,如下所示:
InputStream input = new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8.displayName()));
但是我的问题是这个异常的原因是什么?为什么它会发生在我上面的 JSON 字符串上?我只是想了解为什么在我上面的 JSON 字符串上会发生此异常。使用 UTF-8
是正确的解决方法吗?
这个错误是什么意思Invalid UTF-8 middle byte 0x2d
?
您从 Java Unicode 字符串 jsonString
开始。
然后使用 String.getBytes()
将其转换为字节流。由于您没有指定字节编码,因此使用的平台默认值很可能是 ISO 8859-1。
现在您从 (Data)InputStream
解析 JSON。现在 Avro 似乎使用 UTF-8 来解码字节。当它遇到 é
(0x2d) 时失败,因为它不是有效的 UTF 字节序列。
所以最后是实际编码(ISO 8859-1)和预期编码(UTF-8)不匹配。
你可以像以前一样解决这个问题,或者只是避免从字符串到字节:
Decoder decoder = DecoderFactory.get().jsonDecoder(schema, jsonString);
您可能对使用 Jackson Avro 模块的更方便的方法感兴趣,而不是使用低级 Avro 解码器功能:
https://github.com/FasterXML/jackson-dataformat-avro/issues
您可以在其中提供 Avro Schema,但仍可使用 POJO。
您还可以对 JSON 部分使用常规 JSON Jackson 数据绑定(不同的 ObjectMapper
),并将 JSON 读入 POJO,将 POJO 写入 Avro(或其他组合)。