【问题标题】:Deserialize $ref document pointer using JSON.Net使用 JSON.Net 反序列化 $ref 文档指针
【发布时间】:2016-02-18 10:38:09
【问题描述】:

我已经花了好几个小时试图解决这个问题。似乎有很多帖子提示我遇到的问题,但似乎没有一个帖子对我有用。

我只是想使用 json.net 反序列化我的 json 文档中的 $ref 字段

示例 JSON:

{
  "items": [
    { "$ref": "#/parameters/RequestId" },
    {
      "name": "user",
      "in": "body",
      "description": "User metadata object",
      "required": true
    }
  ],
  "parameters": {
    "RequestId": {
      "name": "X-requestId",
      "in": "header",
      "description": "this is a request id",
      "required": false
    }
  }
}

示例类:

public class Item
{
  public string Name {get;set;}
  public string In {get;set;}
  public string Description {get;set;}
  public bool Required {get;set;}
}

public class RootDoc 
{   
  public List<Item> Items {get;set;}   
  public Dictionary<string, Item> Parameters {get;set;}
}

我的期望:

var doc = JsonConvert.DeserializeObject<RootDoc>(json, new JsonSerializerSettings()
                {
                    MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
                    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                    ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                    Error = delegate (object sender, ErrorEventArgs args)
                    {
                        // Handle all errors
                        args.ErrorContext.Handled = true;
                    }
                });

Assert.IsNotNull(doc);
Assert.IsNotNull(doc.Items);
Assert.IsTrue(doc.Items.Count == 2);
Assert.IsTrue(doc.Items[0].Name == "X-requestId");
Assert.IsTrue(doc.Items[1].Name == "user");

编辑:

我回答了下面的问题。我不敢相信我必须这样做,但它确实有效。

【问题讨论】:

    标签: c# .net json asp.net-web-api json.net


    【解决方案1】:

    哇...所以这就是我为解决问题所做的。我不确定是否有更简单的方法,我不敢相信 json.net 没有提供开箱即用的功能。

    var x = JObject.Parse(json);
                var xx = x.Descendants().ToList().Where(d => d.Path.ToLower().EndsWith("$ref"));
                foreach (var item in xx)
                {
                    if (!item.HasValues)
                        continue;
                    string str = item.First.ToString().TrimStart(new char[] { '#' }).TrimStart(new char[] { '/' });
                    var split = str.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
                JToken token = x;
                for (int i = 0;i<split.Length; i++)
                {
                    token = token[split[i]];
                }
    
                item.Parent.Replace(token);
            }
    
            var doc = JsonConvert.DeserializeObject<RootDoc>(x.ToString(), new JsonSerializerSettings()
            {
                PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                Error = delegate (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args)
                {
                    // Handle all errors
                    args.ErrorContext.Handled = true;
                }
            });
    
            Assert.IsNotNull(doc);
            Assert.IsNotNull(doc.Items);
            Assert.IsTrue(doc.Items.Count == 2);
            Assert.IsTrue(doc.Items[0].Name == "X-requestId");
            Assert.IsTrue(doc.Items[1].Name == "user");
    

    【讨论】:

    • 也许像o1.SelectToken(path).Replace(o2.SelectToken(path)); 这样的东西可以简化代码。
    【解决方案2】:

    您可以使用此代码。

    JObject o = JObject.Parse(json);
    
    JToken tokenToReplace = o.SelectToken("$..$ref");
    string[] s = tokenToReplace.Value<string>().Split('/');
    string a = s[s.Length - 1];
    JToken newToken = o.SelectToken("$.." + a);
    
    JArray items = (JArray)o["items"];
    items.Add(newToken);
    tokenToReplace.Parent.Parent.Remove();
    
    string newJson = o.ToString();
    

    newJson 包含替换的$ref

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-27
      • 2012-04-09
      • 1970-01-01
      相关资源
      最近更新 更多