从多态json到LINQ to Json数据检索 [英] LINQ to Json data retrieval from polymorphic json

查看:82
本文介绍了从多态json到LINQ to Json数据检索的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多态json字符串.看起来是这样的:

I have a polymorphic json string. Here's what it looks like:

{  
   "?xml":{  
      "@version":"1.0",
      "@encoding":"UTF-8"
   },
   "DataFeed":{  
      "@FeedName":"AdminData",
      "Issuer":[  
         {  
            "name":"Apple",
            "symbol":"AAPL-O",
            "active":"1",
            "securities":{  
               "Security":{  
                  "sedol":"B0XXF09",
                  "coverage":{  
                     "Coverage":{  
                        "analyst":{  
                           "@firstName":"Steve",
                           "@lastName":"Jobs",
                           "@rank":"1"
                        }
                     }
                  },
                  "symbolMappingList":{  
                     "SecuritySymbol":{  
                        "symbolset":{  
                           "id":"11",
                           "symbol":"ISIN",
                           "name":"ISIN",
                           "rixmlName":"ISIN",
                           "researchDirect":"S&P"
                        },
                        "symbol":"US44919P5XXX"
                     }
                  },
                  "symbolMapping":{  
                     "entry":{  
                        "int":"11",
                        "SecuritySymbol":{  
                           "@reference":"../../../symbolMappingList/SecuritySymbol"
                        }
                     }
                  },
                  "customFields":{  
                     "customField":[  
                        {  
                           "@name":"ADP",
                           "@type":"Textbox",
                           "values":{  
                              "value":"H0192XX"
                           }
                        },
                        {  
                           "@name":"Top 15",
                           "@type":"Dropdown, multiple choice",
                           "values":null
                        }
                     ]
                  }
               }
            }
         },
         {  
            "name":"Microsoft",
            "symbol":"MSFT-OTC",
            "active":"1",
            "securities":{  
               "Security":{  
                  "sedol":"B8FW54",
                  "coverage":{  
                     "Coverage":{  
                        "analyst":{  
                           "@firstName":"Bill",
                           "@lastName":"Gates",
                           "@rank":"1"
                        }
                     }
                  },
                  "symbolMappingList":{  
                     "SecuritySymbol":[  
                        {  
                           "symbolset":{  
                              "id":"3",
                              "symbol":"CUSIP",
                              "name":"CUSIP",
                              "rixmlName":"CUSIP",
                              "researchDirect":"S&P"
                           },
                           "symbol":"04316A1XX"
                        },
                        {  
                           "symbolset":{  
                              "id":"11",
                              "symbol":"ISIN",
                              "name":"ISIN",
                              "rixmlName":"ISIN",
                              "researchDirect":"S&P"
                           },
                           "symbol":"US04316A10XX"
                        }
                     ]
                  },
                  "symbolMapping":{  
                     "entry":[  
                        {  
                           "int":"3",
                           "SecuritySymbol":{  
                              "@reference":"../../../symbolMappingList/SecuritySymbol"
                           }
                        },
                        {  
                           "int":"11",
                           "SecuritySymbol":{  
                              "@reference":"../../../symbolMappingList/SecuritySymbol[2]"
                           }
                        }
                     ]
                  },
                  "customFields":{  
                     "customField":[  
                        {  
                           "@name":"ADP Security Code",
                           "@type":"Textbox",
                           "values":null
                        },
                        {  
                           "@name":"Top 15",
                           "@type":"Dropdown, multiple choice",
                           "values":null
                        }
                     ]
                  }
               }
            }
         }
      ]
   }
}

有人曾经帮助我进行扩展类,以便我可以检索ADP代码.这是扩展类:

Someone once helped me with an extension class so that I can retrieve the ADP codes. Here's the extension class:

public static class JsonExtensions
{
    public static IEnumerable<JToken> DescendantsAndSelf(this JToken node)
    {
        if (node == null)
            return Enumerable.Empty<JToken>();
        var container = node as JContainer;
        if (container != null)
            return container.DescendantsAndSelf();
        else
            return new[] { node };
    }

    public static IEnumerable<JObject> ObjectsOrSelf(this JToken root)
    {
        if (root is JObject)
            yield return (JObject)root;
        else if (root is JContainer)
            foreach (var item in ((JContainer)root).Children())
                foreach (var child in item.ObjectsOrSelf())
                    yield return child;
        else
            yield break;
    }
}

基于此,这是我的查询:

Based on that, here's my query:

var compInfo = from issuer in feed.SelectTokens("DataFeed.Issuer").SelectMany(i => i.ObjectsOrSelf())
           where (string)issuer["active"] == "1"
           let security = issuer.SelectTokens("securities.Security").SelectMany(s => s.ObjectsOrSelf()).FirstOrDefault()
           let securitySymbol = issuer.SelectTokens("securities.Security.symbolMappingList")
            .SelectMany(s => s.ObjectsOrSelf()).FirstOrDefault()
           where security != null
           select new
{
               CompName = (string)issuer["name"],
               SEDOL = ((string)security["sedol"]).StartsWith("0") ? 
                String.Format("'{0}", (string)security["sedol"]) : (string)security["sedol"],
               ADP = security["customFields"]
                .DescendantsAndSelf()
                .OfType<JObject>()
                .Where(o => (string)o["@name"] == "ADP Security Code")
                .Select(o => (string)o.SelectToken("values.value"))
                .FirstOrDefault(),
               ISIN = security["symbolMappingList"]
                .DescendantsAndSelf()
                .OfType<JObject>()
                .Where(o => (string)o["SecuritySymbol.symbolset.name"] == "ISIN")
                .Select(o => (string)o.SelectToken("SecuritySymbol.symbol"))
                .FirstOrDefault()
};

我能够获得ADP代码.但是,如何获取ISIN代码?我想我已经很接近了,但是我得到了所有的空值.要进行这项工作,我需要更改什么?

I'm able to get the ADP codes. But how can I get the ISIN codes? I think I'm pretty close, but I get all nulls. What do I need to change to make this work?

推荐答案

应为:

   ISIN = security["symbolMappingList"]
    .DescendantsAndSelf()
    .OfType<JObject>()
    .Where(o => (string)o.SelectToken("symbolset.name") == "ISIN")
    .Select(o => (string)o.SelectToken("symbol"))
    .FirstOrDefault()

一些注意事项:

  1. 您不能使用索引器选择深度嵌套的令牌,就像您尝试使用表达式o["SecuritySymbol.symbolset.name"]一样.索引器将仅返回直系子代.您需要使用 SelectToken() 来选择孙子代.

  1. You cannot use indexers to select deeply nested tokens, as you try to do with the expression o["SecuritySymbol.symbolset.name"]. Indexers will only return immediate children. You need to use SelectToken() to select grandchildren.

"SecuritySymbol"属性的值有时是一个对象:

The value of the "SecuritySymbol" property is sometimes an object:

             "SecuritySymbol":{  
                "symbolset":{  

有时是一个数组:

             "SecuritySymbol":[  
                {  
                   "symbolset":{  

取决于其中的项目数.由于这种多态性,您不能只执行SelectToken("SecuritySymbol.symbolset.name").而是使用DescendantsAndSelf()递归搜索SecuritySymbol及其子代(无论是否嵌入在数组中)的值,以找到具有适当的"symbolset.name"子标记的对象.

Depending upon the number of items therein. Because of this polymorphism, you cannot just do SelectToken("SecuritySymbol.symbolset.name"). Instead use DescendantsAndSelf() to recursively search the value of SecuritySymbol and its descendants (whether embedded in an array or not) for an object with the appropriate "symbolset.name" child token.

这是一个更新的查询,已进行了稍微优化,以消除对SelectToken的重复调用,并根据"sedol"名称进行过滤:

Here is an updated query that has been slightly optimized to eliminate duplicate calls to SelectToken and also to filter on the "sedol" name:

var filterString = "B0XXF09"; // Null if filtering is not desired

var compInfo = from issuer in feed.SelectTokens("DataFeed.Issuer").SelectMany(i => i.ObjectsOrSelf())
               where (string)issuer["active"] == "1"
               let security = issuer.SelectTokens("securities.Security").SelectMany(s => s.ObjectsOrSelf()).FirstOrDefault()
               where security != null
               let sedol = (string)security["sedol"]
               where (sedol != null && filterString == null || sedol.Contains(filterString))
               select new
               {
                   CompName = (string)issuer["name"],
                   SEDOL = sedol.StartsWith("0") ? String.Format("'{0}", sedol) : sedol,
                   ADP = security["customFields"]
                    .DescendantsAndSelf()
                    .OfType<JObject>()
                    .Where(o => (string)o["@name"] == "ADP Security Code")
                    .Select(o => (string)o.SelectToken("values.value"))
                    .FirstOrDefault(),
                   ISIN = security["symbolMappingList"]
                    .DescendantsAndSelf()
                    .OfType<JObject>()
                    .Where(o => (string)o.SelectToken("symbolset.name") == "ISIN")
                    .Select(o => (string)o.SelectToken("symbol"))
                    .FirstOrDefault()
               };

这篇关于从多态json到LINQ to Json数据检索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆