由于Encoding和Escape字符问题,Http请求结束为错误请求

时间:2018-03-15 05:18:39

标签: c# .net encoding f#

注意:代码在F#中,但标记C#,因为它是从.net转换为json 时.net上的一般编码和转义字符问题,请查看在页面底部的输出处。

以下请求最终导致错误请求,请查看任何差异,尤其是Encoding.Default.GetString,然后再编码回System.Text.Encoding.ASCII.GetBytes

上下文:对象被序列化并写入PUT请求的主体,最终被视为错误的请求400. JSON被正确序列化,我可以看到带有Console.WriteLine的字符串

我从F# snippets

获取了JSON编码示例
let update (schema: Article) : Article = 

    let url = "http://example.com"

    use memoryStream = new MemoryStream() 
    (new DataContractJsonSerializer(typeof<Article>)).WriteObject(memoryStream, schema) 
    let d = Encoding.Default.GetString(memoryStream.ToArray()) // I suspect problem may be here
    let data : byte[] = System.Text.Encoding.ASCII.GetBytes(d); // or here

    let request = WebRequest.Create(url) :?> HttpWebRequest
    request.Method <- "PUT"
    request.ContentType <- "application/json;charset=UTF-8"
    request.Accept <- "application/json;charset=UTF-8"
    request.ContentLength <- (int64)data.Length

    use requestStream = request.GetRequestStream() 
    requestStream.Write(data, 0, data.Length)
    requestStream.Flush()
    requestStream.Close()

    let response = request.GetResponse() :?> HttpWebResponse
    use reader = new StreamReader(response.GetResponseStream())
    use memoryStream = new MemoryStream(ASCIIEncoding.Default.GetBytes(reader.ReadToEnd())) 
    let result = (new DataContractJsonSerializer(typeof<Article>)).ReadObject(memoryStream) :?> Article

    reader.Close()
    response.Close()
    request.Abort()

    result

进一步发现

我能够获得Charles Proxy,我看到正向斜杠已经在输出序列化的json中转义到服务器。

实际输出:使用转义斜线\ /

\/publication\/d40a4e4c-d6a3-45ae-98b3-924b31d8712a\/altasset\/c42d0df7-a563-4bb5-b7fa-313e6a98032f\/

预期输出:它们应该只有正斜杠,不能转义字符。

  

/公开/ d40a4e4c-d6a3-45ae-98b3-924b31d8712a ....

我想在编码过程中导致角色被转义的东西,有没有办法解决它?

修改

我还注意到memoryStream.ToArray()返回byte[]所以我没有通过编码,而是尝试了以下内容,但它没有任何区别。

let data : byte[] = memoryStream.ToArray()

requestStream.Write(data, 0, data.Length)

在Charles代理中,我看到破管消息。

enter image description here

1 个答案:

答案 0 :(得分:1)

添加对Newtonsoft.Json NuGet包的引用,并将其添加到F#文件的顶部:

open Newtonsoft.Json

然后尝试将此作为更新方法的主体(它显式使用UTF-8编码而不是ASCII或平台默认值):

let url = "http://example.com"

let serialized = JsonConvert.SerializeObject(schema)
let data : byte[] = Encoding.UTF8.GetBytes(serialized)

let request = WebRequest.Create(url) :?> HttpWebRequest
request.Method <- "PUT"
request.ContentType <- "application/json;charset=UTF-8"
request.Accept <- "application/json;charset=UTF-8"
request.ContentLength <- (int64)data.Length

use requestStream = request.GetRequestStream() 
requestStream.Write(data, 0, data.Length)
requestStream.Flush()
requestStream.Close()

let response = request.GetResponse() :?> HttpWebResponse
use reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)
let result = JsonConvert.DeserializeObject<Article>(reader.ReadToEnd())

reader.Close()
response.Close()
request.Abort()

result

除非您正在使用的服务器也在使用DataContractJsonSerializer(它逃脱&#34; /&#34; as&#34; \ /&#34;),否则你可能会更好Newtonsoft。在UTF-8编码问题出现之前修复UTF-8编码问题并没有什么坏处(它看起来不像是在发送/接收任何非ASCII文本,但在现实世界中不可避免地会发生这种情况)。 / p>