org.codehaus.jackson.JsonParseException: 无效的 UTF-8 中间字节 0xdf

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18175899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 19:42:04  来源:igfitidea点击:

org.codehaus.Hymanson.JsonParseException: Invalid UTF-8 middle byte 0xdf

jsonHymanson

提问by 123456789

I'm using the Hymanson framework for marshaling and unmarshalling data between JSON and Java. Everything works well, as long the input doesn't contain any characters like:

我正在使用 Hymanson 框架在 JSON 和 Java 之间编组和解组数据。一切正常,只要输入不包含任何字符,如:

  • ?
  • ?
  • ü
  • ?
  • ?
  • ü
  • ?
  • ?
  • ?
  • ü
  • ?
  • ?
  • ü
  • ?

For input data I tried:

对于我尝试过的输入数据:

String jsonData = "{\"id\":1,\"street\":\"Stra?e\",\"number\":\"1c\",\"zipCode\":1111,\"city\":\"MyCity\"}";

as well as:

也:

String jsonData = "{\"id\":1,\"street\":\"Stra\u00DFe\",\"number\":\"1c\",\"zipCode\":1111,\"city\":\"MyCity\"}";

and all the time I get the same exception.

并且我总是遇到相同的异常。

The mapping from json data to java entity object is done via:

从 json 数据到 java 实体对象的映射是通过以下方式完成的:

/*
 * Convert stream to data entity
 */
ObjectMapper m = new ObjectMapper();
T entity = (T) m.readValue(stringToStream(jsonData), readableClass);

I also perform a json data validation which works like expected, also with the above chars.

我还执行了一个 json 数据验证,它按预期工作,也使用上述字符。

How should such data be handled?

应该如何处理这些数据?

UPDATEThese are the important parts of the MessageBodyReaderclass

更新这些是MessageBodyReader课程的重要部分

@Override
public T readFrom(Class<T> type, Type genericType,
        Annotation[] annotations, MediaType mediaType,
        MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
        throws IOException, WebApplicationException {

    final String jsonData = getStringFromInputStream(entityStream);
    System.out.println(jsonData);

    InputStream isSchema = new FileInputStream(jsonSchemaFile);
    String jsonSchema = getStringFromInputStream(isSchema);

    /*
     * Perform JSON data validation against schema
     */
    validateJsonData(jsonSchema, jsonData);

    /*
     * Convert stream to data entity
     */
    ObjectMapper m = new ObjectMapper();
    T entity = (T) m.readValue(stringToStream(jsonData), readableClass);

    return entity;
}

/**
 * Validate the given JSON data against the given JSON schema
 * 
 * @param jsonSchema
 *            as String
 * @param jsonData
 *            as String
 * @throws MessageBodyReaderValidationException
 *             in case of an error during validation process
 */
private void validateJsonData(final String jsonSchema, final String jsonData)
        throws MessageBodyReaderValidationException {
    try {
        final JsonNode d = JsonLoader.fromString(jsonData);
        final JsonNode s = JsonLoader.fromString(jsonSchema);

        final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
        JsonValidator v = factory.getValidator();

        ProcessingReport report = v.validate(s, d);
        System.out.println(report);
        if (!report.toString().contains("success")) {
            throw new MessageBodyReaderValidationException(
                    report.toString());
        }

    } catch (IOException e) {
        throw new MessageBodyReaderValidationException(
                "Failed to validate json data", e);
    } catch (ProcessingException e) {
        throw new MessageBodyReaderValidationException(
                "Failed to validate json data", e);
    }
}

/**
 * Taken from <a href=
 * "http://www.mkyong.com/java/how-to-convert-inputstream-to-string-in-java/"
 * >www.mkyong.com</a>
 * 
 * @param is
 *            {@link InputStream}
 * @return Stream content as String
 */
private String getStringFromInputStream(InputStream is) {
    BufferedReader br = null;
    StringBuilder sb = new StringBuilder();

    String line;
    try {

        br = new BufferedReader(new InputStreamReader(is));
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (br != null) {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    return sb.toString();
}

private InputStream stringToStream(final String str) {
    return new ByteArrayInputStream(str.getBytes());
}

回答by Jk1

JSON specification states, that only valid encodings are UTF-8, UTF-16 and UTF-32. No other encodings (like Latin-1) can be used. Your stringToStream implementation is not setting the encoding explicitly, so system default is used. That is how you got non-utf stream. On the next step Jakson is trying to parse the stream using one of UTF encodings (it has detection algorithm built in) and fails. Try setting an explicit encoding:

JSON 规范指出,只有有效的编码是 UTF-8、UTF-16 和 UTF-32。不能使用其他编码(如 Latin-1)。您的 stringToStream 实现未明确设置编码,因此使用系统默认值。这就是您获得非 utf 流的方式。在下一步中,Jakson 尝试使用其中一种 UTF 编码(它具有内置检测算法)解析流并失败。尝试设置显式编码:

new ByteArrayInputStream(str.getBytes("UTF-8"));

回答by StaxMan

You already got an answer, but one obvious question here is this: why are you converting from a Stringto a stream? That is unnecessary and wasteful thing to do -- so just pass the String as-is. This will also remove the problem; Strings do not have encoding per se (that is: there is just a single in-memory representation and no conversions are needed).

您已经得到了答案,但这里有一个明显的问题:为什么要从 aString转换为流?这是不必要且浪费的事情——所以只需按原样传递字符串。这也将消除问题;字符串本身没有编码(即:只有一个内存中的表示,不需要转换)。