【问题标题】:Json.NET: deserialize any kind of objectJson.NET:反序列化任何类型的对象
【发布时间】:2020-08-26 15:01:33
【问题描述】:

我有一个如下所示的 json 文件:

{
  "tags": {
    "t1": {
      "description": "bar"
    },
    "t2": {
      "description": {
        "$ref": "./t2.md"
      }
    }
  }
}

我想像这样用 Json.NET 反序列化它:

var baz = JsonConvert.DeserializeObject<Baz>(File.ReadAllText(@"baz.json"));

//...

internal class Baz
{
    [JsonProperty("tags")]
    internal Tags Tags;
}

internal class Tags: Dictionary<string, Tag>
{
}

internal class Tag
{
    [JsonProperty("description")]
    internal Description Description;
}

internal class Description // FIXME: can be string, Dictionary or List
{
}

如何定义Description 类,它可以是stringDictionary&lt;string, string&gt;?我试过继承一个抽象方法,但是反序列化器总是返回null

【问题讨论】:

  • 描述的字段'$ref'可以有别的名字吗?
  • 不,它要么是字符串,要么是 {"$ref": "..."} 对象。
  • @RoarS。它是一个带有一个 Key-Value-Pair 的 JS 对象,因此相当于一个带有一个条目的字典。
  • @Vernou 谢谢,这与您发布的第二个链接中的obj["$ref"] 合作。请添加答案,以便我接受。

标签: c# json json.net


【解决方案1】:

您可以创建自定义反序列化器: https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm

public class DescriptionConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return false;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.String)
        {
            //If is string, return the string
            return serializer.Deserialize(reader, objectType);
        }
        else
        {
            //If not string, try get the field '$ref'
            var obj = JObject.Load(reader);
            if (obj["$ref"] != null)
                return obj["$ref"].ToString();
            else
                throw new InvalidOperationException("Invalid Json");
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后你可以在你的模型中指定这个转换器:

internal class Baz
{
    [JsonProperty("tags")]
    internal Tags Tags;
}

internal class Tags : Dictionary<string, Tag>
{
}

internal class Tag
{
    [JsonProperty("description")]
    [JsonConverter(typeof(DescriptionConverter))]
    internal string Description;
}

最后,你可以反序列化 json 了:

static void Main(string[] args)
{
    string json = @"{
        'tags': {
            't1': {
                'description': 'bar'
            },
            't2': {
                'description': {
                    '$ref': './t2.md'
                }
            }
        }
    }";
    var baz = JsonConvert.DeserializeObject<Baz>(json);
    Console.WriteLine("t1 : " + baz.Tags["t1"].Description);
    Console.WriteLine("t2 : " + baz.Tags["t2"].Description);
}

输出:

t1 : bar
t2 : ./t2.md

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多