JObject.Load JsonReaderException

时间:2018-08-21 08:49:50

标签: c# .net json json.net

我有这样的json:

{  
   "_id":{  
      "$oid":"5b7bc6acc223c11047485dd5"
   },
   "id":"28679e7d-0bca-40b0-b033-044df2bb1b47",
   "type":"some string"   
}

以及此类:

public class Foo 
{
    private readonly JObject _json;

    internal Foo(JObject data)
    {
        _json = data;
    }

    public override Guid Id => (_json["id"]).ToObject<Guid>();

    public override string Type => _json["type"]?.ToString();
}

我想将此字符串反序列化为Foo实例。我有以下反序列化器:

public class FooConverter : JsonConverter<Foo>
{
    public override void WriteJson(JsonWriter writer, Foo value, JsonSerializer serializer)
    {
        writer.WriteRaw(value.GetJsonData().ToString());
    }

    public override Foo ReadJson(JsonReader reader, Type objectType, Foo existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var obj = JObject.Load(reader); // Here's an exception
        return new Foo(obj);
    }
}

如您所见,我的json有_id字段,Foo没有。当我打电话

JsonConvert.DeserializeObject<Foo>(jsonString);

我收到此异常:

  

'Newtonsoft.Json.JsonReaderException:'解析值时遇到意外字符:O。路径'_id',第1行,位置10。''

是否可以避免此异常并正确加载json?

2 个答案:

答案 0 :(得分:1)

以下json字符串

{  
   "_id":{  
      "$oid":"5b7bc6acc223c11047485dd5"
   },
   "id":"28679e7d-0bca-40b0-b033-044df2bb1b47",
   "type":"some string"   
}

可以映射到以下类别:

public class Foo
{
    [JsonProperty("_id")]
    public FooId FooId { get; set; }

    [JsonProperty("id")]
    public Guid Id { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }
}

public class FooId
{
    [JsonProperty("$oid")]
    public string Oid { get; set; }
}

测试代码:

using System;
using Newtonsoft.Json;

class Program
{
    static void Main(string[] args)
    {
        string json = @"{  
   ""_id"":{  
      ""$oid"":""5b7bc6acc223c11047485dd5""
   },
   ""id"":""28679e7d-0bca-40b0-b033-044df2bb1b47"",
   ""type"":""some string""   
}";

        var foo = JsonConvert.DeserializeObject<Foo>(json);

        Console.Read();
    }
}

答案 1 :(得分:0)

如果除了private readonly JObject _json;Id的获取者之外,不需要其他Type属性,可以通过如下方法直接反序列化为Foo来简化代码: / p>

更改您的Foo班级:

public class Foo
{
    [JsonProperty("id")]
    public override Guid Id {get;set;}

    [JsonProperty("type")]
    public override string Type {get;set;}
}

需要JsonProperty属性,因为json字符串中的元素键与Foo类中的元素键不同(区分大小写)。

然后您可以像这样反序列化json:

var json = "some json";
var foo = JsonConvert.DeserializeObject<Foo>(json);

json _id元素只是被忽略。

这样做的时候,您可以省略创建自定义转换器FooConverter的过程,而您的Foo类更简洁。