输入字符串已编码,需要原始字符串 - Java 编码

Input String Is Encoded, Need The Original String - Java Code

我有一个 REST Web 服务,它接受 JSON 形式的输入(作为多部分表单数据)。

@POST
@Consumes ({"application/ds-json",MediaType.APPLICATION_FORM_URLENCODED,MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML,"text/html",MediaType.MULTIPART_FORM_DATA})
@Produces({ text_html, "application/ds-json" })
@Path("/abc")
public Response abc(@Context HttpServletRequest req, @Context HttpServletResponse response){
           .
           .
           .
           .
     String strInput = inputJSON.getString("data");
           .
           .
           .
}

我发送的输入 JSON 是 {"data":"Sécurité"} 而我得到的字符串 strInput 的值是 Sécurité

我尝试java.net.URLDecoder.decode(strInput, "iso-8859-1")将其解码回其原始字符,但失败了。

我也尝试了 String strInput = new String((inputJSON.getString("data")).getBytes(), "iso-8859-1"); 预期传入的字符将根据要求存储在变量 strInput 中,但失败了。

我感觉完全迷失在这里。有人可以帮忙吗?


编辑:

为了更清楚,下面是我如何将 JSON 发送到此服务(仅用于测试目的):

  1. 我创建了一个 HTML 页面,可以向网络服务发送 POST 请求

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Insert title here</title>
</head>

<body>

  <form action="http://localhost:8080/xxxx/abc" method="POST" enctype="multipart/form-data">

    JSON:
    <input type="text" name="data">
    <input type="submit" name="submit">
  </form>
</body>

</html>

  1. 在页面中,我输入的文本为Sécurité

所有 Java 个字符使用 UTF-16 存储在内存中。问题来自传输的字节。你写了

I send is {"data":"Sécurité"}

它只是一种表示形式,它不提供有关用于传输文本的字节表示形式的信息。如果使用的表示不是响应的一部分,则接收者无法发明它。如果缺少编码,发送方和消费者都必须依赖相同的约定。例如,某些协议有默认值,但这意味着发送方和接收方都遵守标准默认值,并且它们还必须与规范同步(默认编码随时间变化)。

根据您的具体问题,当您的 Java 请求处理器收到发送的字节时,它已使用 Charset 将其转换为 Java char。不支持的字节在此转换中丢失。

可能的解决方案:

  1. 使发件人始终指定使用的编码
  2. 添加一个请求过滤器,该过滤器根据某些请求元数据(即 User-Agent)猜测默认编码
  3. 停止使用 IE(据我所知,IE8 在编码方面有问题,尤其是在 XHR 方面)

注:一篇must-read文章:The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

尝试添加 Consumes 参数:

+";charset=utf-8"

例如:

MediaType.APPLICATION_JSON +";charset=utf-8"

我用它,但输出正常。

谢谢大家,我设法解决了这个问题,@kayaman 的评论帮助我到达这里

What you're seeing is UTF-8 data decoded as ISO-8859-1. – Kayaman

我刚刚按照 ISO-8859-1 编码将输入字符串 strInput 转换为字节,并再次按照 UTF-8 编码创建了新字符串。这对我有用。

byte[] inputBytes = strInput.getBytes("iso-8859-1");
strInput = new String(inputBytes, "UTF-8"); 

早些时候我将输入字符串的字节作为 byte[] inputBytes = strInput.getBytes(); 获取,默认情况下它返回给我 UTF-8 解码字节,它比我预期的字节多(我向@Kayaman 提到了这一点):

@Kayaman Yes, you are very much correct and I tested that in a separate test class. But in my current case(the web service), the data that I'm getting as input seems to be corrupted somehow. I tried printing bytes of both the input and the expected string: byte[] s = strInput.getBytes("UTF-8"); byte[] s1 = "Sécurité".getBytes("UTF-8"); their result: s = [83, -61, -125, -62, -87, 99, 117, 114, 105, 116, -61, -125, -62, -87] s1 = [83, -61, -87, 99, 117, 114, 105, 116, -61, -87] both these should have been same, but I'm getting extra bytes {-125, -62} – Ankan Priya

然而,由于字符串是 ISO-8859-1 编码形式,我需要使用相同的解码方案获取字节并且它有效(参见上面的代码片段)