输入字符串已编码,需要原始字符串 - 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 发送到此服务(仅用于测试目的):
- 我创建了一个 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>
- 在页面中,我输入的文本为
Sécurité
所有 Java 个字符使用 UTF-16
存储在内存中。问题来自传输的字节。你写了
I send is {"data":"Sécurité"}
它只是一种表示形式,它不提供有关用于传输文本的字节表示形式的信息。如果使用的表示不是响应的一部分,则接收者无法发明它。如果缺少编码,发送方和消费者都必须依赖相同的约定。例如,某些协议有默认值,但这意味着发送方和接收方都遵守标准默认值,并且它们还必须与规范同步(默认编码随时间变化)。
根据您的具体问题,当您的 Java 请求处理器收到发送的字节时,它已使用 Charset 将其转换为 Java char
。不支持的字节在此转换中丢失。
可能的解决方案:
- 使发件人始终指定使用的编码
- 添加一个请求过滤器,该过滤器根据某些请求元数据(即
User-Agent
)猜测默认编码
- 停止使用 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
编码形式,我需要使用相同的解码方案获取字节并且它有效(参见上面的代码片段)
我有一个 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 发送到此服务(仅用于测试目的):
- 我创建了一个 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>
- 在页面中,我输入的文本为
Sécurité
所有 Java 个字符使用 UTF-16
存储在内存中。问题来自传输的字节。你写了
I send is
{"data":"Sécurité"}
它只是一种表示形式,它不提供有关用于传输文本的字节表示形式的信息。如果使用的表示不是响应的一部分,则接收者无法发明它。如果缺少编码,发送方和消费者都必须依赖相同的约定。例如,某些协议有默认值,但这意味着发送方和接收方都遵守标准默认值,并且它们还必须与规范同步(默认编码随时间变化)。
根据您的具体问题,当您的 Java 请求处理器收到发送的字节时,它已使用 Charset 将其转换为 Java char
。不支持的字节在此转换中丢失。
可能的解决方案:
- 使发件人始终指定使用的编码
- 添加一个请求过滤器,该过滤器根据某些请求元数据(即
User-Agent
)猜测默认编码 - 停止使用 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
编码形式,我需要使用相同的解码方案获取字节并且它有效(参见上面的代码片段)