【问题标题】:invalid JSON generated by default Restsharp JSON serialiserRestsharp JSON 序列化程序默认生成的无效 JSON
【发布时间】:2014-03-20 18:37:00
【问题描述】:

我的代码如下。当我发布一个包含 \v 的 JSON 正文时,服务器会收到它无法解析的 JSON。有关如何使其工作的任何帮助?

编辑:好吧,关于我的服务器无法解析它的论点很弱,但http://jsonlint.com/ 也抱怨它。 :)

在我的 emacs 中是这样的:

{"key":"a^Kb"}

^K 我认为是单个字符。

代码:

using RestSharp;
using System;
using System.Collections.Generic;

namespace testapp
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new RestClient();
            var request = new RestRequest();

            request.Method = Method.POST;
            request.RequestFormat = DataFormat.Json;
            request.Resource = "http://example.com/";

            var data = new Dictionary<string, string>();
            data.Add("key", "a\vb");
            request.AddBody(data);

            var response = client.Execute<Dictionary<string, string>>(request);
        }
    }
}

【问题讨论】:

  • 它序列化成什么? PostSharp 生成{"key":"a\u000bb"},JSONLint 接受它为有效。
  • 顺便说一句,我说的是“PostSharp”,但我的意思是“Json.NET”。我没想到,RestSharp 在名称上与 PostSharp 太接近了。此外,RestSharp 通过线路发送文字 0b(即 \v)字节。也许这在服务器上没有正确解释。
  • 我正在使用 Ruby Sinatra,我阅读了 request.body.rewind 的正文,然后是 JSON.parse request.body.read...

标签: c# restsharp


【解决方案1】:

默认的 RestSharp JSON 序列化器将其序列化为等效于 C# 字符串"{\"key\":\"a\vb\"}";也就是说,它通过网络将\v 作为原始字节(0b)发送。这就是您的服务器无法读取它的原因。我不确定这是否是合法的 JSON,但无论如何都有办法逃避这样的字符以避免问题。

我建议使用 Json.NET 来反序列化您的 JSON。如果您使用the following class(最初是RestSharp 的一部分)作为序列化程序,它将使用Json.NET 并且应该可以正常工作,因为它将通过网络将\v 编码为\u000b。代码(无 cmets,为清楚起见已重命名)在这里复制以供参考:

public class JsonNetSerializer : ISerializer
{
    private readonly Newtonsoft.Json.JsonSerializer _serializer;

    public JsonNetSerializer()
    {
        ContentType = "application/json";
        _serializer = new Newtonsoft.Json.JsonSerializer
        {
            MissingMemberHandling = MissingMemberHandling.Ignore,
            NullValueHandling = NullValueHandling.Include,
            DefaultValueHandling = DefaultValueHandling.Include
        };
    }

    public JsonNetSerializer(Newtonsoft.Json.JsonSerializer serializer)
    {
        ContentType = "application/json";
        _serializer = serializer;
    }

    public string Serialize(object obj)
    {
        using (var stringWriter = new StringWriter())
        {
            using (var jsonTextWriter = new JsonTextWriter(stringWriter))
            {
                jsonTextWriter.Formatting = Formatting.Indented;
                jsonTextWriter.QuoteChar = '"';

                _serializer.Serialize(jsonTextWriter, obj);

                var result = stringWriter.ToString();
                return result;
            }
        }
    }

    public string DateFormat { get; set; }
    public string RootElement { get; set; }
    public string Namespace { get; set; }
    public string ContentType { get; set; }
}

要使用它,请添加以下行:

request.JsonSerializer = new JsonNetSerializer();

它会像这样序列化:

{
  "key": "a\u000bb"
}

根据JSONLint,这是完全有效的。

【讨论】:

  • 这个答案是正确的,但除了执行它,我们仍然可能会遇到麻烦。添加 Rest 消息正文时,我们必须提供真实对象,而不是序列化为 json 字符串的对象,因为它会尝试将 json 字符串序列化为 json,这会引发相同的错误。
猜你喜欢
  • 1970-01-01
  • 2013-06-26
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多