【问题标题】:Proper Json.net System.Object Round-trip?正确的 Json.net System.Object 往返?
【发布时间】:2012-06-05 18:43:28
【问题描述】:

使用 Newtonsoft.Json 库,想象一下我有

public class Test
{
   public Object Obj { get; set; }
}

现在,尝试像这样序列化它

var json = JsonConvert.SerializeObject(new Test(){ Obj = new Uri(@"http://www.google.com") });

...会给我以下 JSON

{
    "Obj": "http://www.google.com"
}

这显然不足以将其反序列化回 Uri 对象,事实上,尝试反序列化它会给我一个 String 对象。

是否有任何现有方法可以正确序列化和反序列化此处的类型信息,以便将对象作为 Uri 而不是 String 读回?在这种特殊情况下,我只是尝试与 .NET 应用程序进行互操作,并且反序列化确切的类型非常重要。

提前致谢。

【问题讨论】:

    标签: c# .net json.net


    【解决方案1】:

    如果要将字符串转换回 Uri,可以使用自定义转换器属性

    转换器

    public class UriConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.String)
            {
                //try to create uri out of the string
                Uri uri;
                if(Uri.TryCreate(reader.Value.ToString(), UriKind.Absolute, out uri))
                {
                    return uri;
                }
                //just a string -> return string value
                return reader.Value;
            }
    
            if (reader.TokenType == JsonToken.Null)
            {
                return null;
            }
    
            throw new InvalidOperationException("Unable to process JSON");
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (null == value)
            {
                writer.WriteNull();
                return;
            }
    
            if (value is Uri)
            {
                writer.WriteValue(((Uri)value).OriginalString);
                return;
            }
    
            throw new InvalidOperationException("Unable to process JSON");
        }
    }
    

    以及使用属性

     [JsonConverter(typeof(UriConverter))]
     public object Obj {get;set;}
    

    然后您应该能够确定底层对象是否类似于 Uri

      var data = JsonConvert.DeserializeObject<YourObject>(yourJSONString);
      if (data.Obj is Uri)
      {
           ... add logic here
      }
      else
      {
           ... not Uri different logic
      }
    

    您也可以查看这篇文章以获取更多信息Json.NET Uri (de)serialization errors

    【讨论】:

    • 谢谢。如果已知 System.Object 始终是 Uri,这确实可以解决问题,但不幸的是它不是(否则我只会更改类声明中的类型)。
    • +1 太棒了,我已经使用 JSON.NET 多年了,不知道它有这么复杂!
    • 您应该能够重写转换器以使用您的场景,识别字符串是否为 Uri 并相应地将其返回为 Uri。我会为你的场景重写转换器
    • 我还想知道如果 Uri 嵌套在 Obj 内部,这个解决方案是否足够(即 Obj 不是 Uri 对象,但例如,一个 Object[] 也包含一个 Uri ...) .我承认我很生气 Json.net 会无法控制地将我所有的 Uri 对象强制为字符串......
    • 反序列化为对象类型通常是个坏主意。通常,一个属性应该只期望一个类型。最新更新是否适合您的场景?
    【解决方案2】:

    JSON 只知道 JavaScript 数据类型:字符串、数字和布尔值。 URL 不在列表中。

    事实上,JSON 的整个 POINT 就是允许松散类型的传输。如果您想要强类型传输,请查看更强大的传输协议,例如 WCF 二进制序列化。

    【讨论】:

    • 虽然我一般同意你关于 JSON 允许松散类型传输的意图,但 Json.net 在 .NET 类型方面具有灵活性(通过特殊的 $type 属性和 TypeNameHandling 设置)。只是碰巧将 Uri 特例转换为 String...无论如何,谢谢,我会考虑 WCF 二进制序列化。
    猜你喜欢
    • 2014-09-15
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-27
    • 2021-11-30
    • 1970-01-01
    相关资源
    最近更新 更多