我试图获得一份SEDOL& s; ADP值。以下是我的json文本:
{
"DataFeed" : {
"@FeedName" : "AdminData",
"Issuer" : [{
"id" : "1528",
"name" : "ZYZ.A a Test Company",
"clientCode" : "ZYZ.A",
"securities" : {
"Security" : {
"id" : "1537",
"sedol" : "SEDOL111",
"coverage" : {
"Coverage" : [{
"analyst" : {
"@id" : "164",
"@clientCode" : "SJ",
"@firstName" : "Steve",
"@lastName" : "Jobs",
"@rank" : "1"
}
}, {
"analyst" : {
"@id" : "261",
"@clientCode" : "BG",
"@firstName" : "Bill",
"@lastName" : "Gates",
"@rank" : "2"
}
}
]
},
"customFields" : {
"customField" : [{
"@name" : "ADP Security Code",
"@type" : "Textbox",
"values" : {
"value" : "ADPSC1111"
}
}, {
"@name" : "Top 10 - Select one or many",
"@type" : "Dropdown, multiple choice",
"values" : {
"value" : ["Large Cap", "Cdn Small Cap", "Income"]
}
}
]
}
}
}
}, {
"id" : "1519",
"name" : "ZVV Test",
"clientCode" : "ZVV=US",
"securities" : {
"Security" : [{
"id" : "1522",
"sedol" : "SEDOL112",
"coverage" : {
"Coverage" : {
"analyst" : {
"@id" : "79",
"@clientCode" : "MJ",
"@firstName" : "Michael",
"@lastName" : "Jordan",
"@rank" : "1"
}
}
},
"customFields" : {
"customField" : [{
"@name" : "ADP Security Code",
"@type" : "Textbox",
"values" : {
"value" : "ADPS1133"
}
}, {
"@name" : "Top 10 - Select one or many",
"@type" : "Dropdown, multiple choice",
"values" : {
"value" : ["Large Cap", "Cdn Small Cap", "Income"]
}
}
]
}
}, {
"id" : "1542",
"sedol" : "SEDOL112",
"customFields" : {
"customField" : [{
"@name" : "ADP Security Code",
"@type" : "Textbox",
"values" : {
"value" : "ADPS1133"
}
}, {
"@name" : "Top 10 - Select one or many",
"@type" : "Dropdown, multiple choice",
"values" : {
"value" : ["Large Cap", "Cdn Small Cap", "Income"]
}
}
]
}
}
]
}
}
]
}
}
这是我到目前为止的代码:
var compInfo = feed["DataFeed"]["Issuer"]
.Select(p => new {
Id = p["id"],
CompName = p["name"],
SEDOL = p["securities"]["Security"].OfType<JArray>() ?
p["securities"]["Security"][0]["sedol"] :
p["securities"]["Security"]["sedol"]
ADP = p["securities"]["Security"].OfType<JArray>() ?
p["securities"]["Security"][0]["customFields"]["customField"][0]["values"]["value"] :
p["securities"]["Security"]["customFields"]["customField"][0]["values"]["value"]
});
我得到的错误是:
使用无效键值访问JArray值:&#34; sedol&#34;。 Int32数组 预期指数
我认为我真的很接近搞清楚这一点。我该怎么做来修复代码?如果有替代方法可以获取SEDOL
和ADP value
,请告诉我们吗?
[UPDATE1] 我开始使用动态ExpandoObject。这是我到目前为止使用的代码:
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json, new ExpandoObjectConverter());
foreach (dynamic element in obj)
{
Console.WriteLine(element.DataFeed.Issuer[0].id);
Console.WriteLine(element.DataFeed.Issuer[0].securities.Security.sedol);
Console.ReadLine();
}
但我现在收到错误'ExpandoObject' does not contain a definition for 'DataFeed' and no extension method 'DataFeed' accepting a first argument of type 'ExpandoObject' could be found
。 注意:我知道这个json文本格式不正确。一个实例有一个阵列&amp;另一个是对象。我希望代码足够敏捷以处理这两个实例。
[UPDATE2] 感谢@dbc帮助我完成了我的代码。我已经更新了上面的json文本,以便与我当前的环境非常匹配。我现在能够获得SEDOL&amp; ADP代码。但是,当我试图获得第一位分析师时,我的代码只能处理对象,并为属于数组的分析人员生成空值。这是我目前的代码:
var compInfo = from issuer in feed.SelectTokens("DataFeed.Issuer").SelectMany(i => i.ObjectsOrSelf())
let security = issuer.SelectTokens("securities.Security").SelectMany(s => s.ObjectsOrSelf()).FirstOrDefault()
where security != null
select new
{
Id = (string)issuer["id"], // Change to (string)issuer["id"] if id is not necessarily numeric.
CompName = (string)issuer["name"],
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(),
Analyst = security["coverage"]
.DescendantsAndSelf()
.OfType<JObject>()
.Select(jo => (string)jo.SelectToken("Coverage.analyst.@lastName"))
.FirstOrDefault(),
};
我需要更改为始终选择第一位分析师?
答案 0 :(得分:6)
如果你想要所有的SEDOL&amp;每个ADP值与相关的发行者ID和CompName相关,您可以这样做:
var compInfo = from issuer in feed.SelectTokens("DataFeed.Issuer").SelectMany(i => i.ObjectsOrSelf())
from security in issuer.SelectTokens("securities.Security").SelectMany(s => s.ObjectsOrSelf())
select new
{
Id = (long)issuer["id"], // Change to (string)issuer["id"] if id is not necessarily numeric.
CompName = (string)issuer["name"],
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(),
};
使用扩展方法:
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;
}
}
然后
Console.WriteLine(JsonConvert.SerializeObject(compInfo, Formatting.Indented));
产地:
[ { "Id": 1528, "CompName": "ZYZ.A a Test Company", "SEDOL": "SEDOL111", "ADP": "ADPSC1111" }, { "Id": 1519, "CompName": "ZVV Test", "SEDOL": "SEDOL112", "ADP": "ADPS1133" }, { "Id": 1519, "CompName": "ZVV Test", "SEDOL": "SEDOL112", "ADP": "ADPS1133" } ]
但是,在您迄今为止编写的查询中,您似乎只是尝试仅返回第一个 SEDOL&amp;每个发行人的ADP。如果这真的是你想要的,那就做:
var compInfo = from issuer in feed.SelectTokens("DataFeed.Issuer").SelectMany(i => i.ObjectsOrSelf())
let security = issuer.SelectTokens("securities.Security").SelectMany(s => s.ObjectsOrSelf()).FirstOrDefault()
where security != null
select new
{
Id = (long)issuer["id"], // Change to (string)issuer["id"] if id is not necessarily numeric.
CompName = (string)issuer["name"],
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(),
};
结果是:
[ { "Id": 1528, "CompName": "ZYZ.A a Test Company", "SEDOL": "SEDOL111", "ADP": "ADPSC1111" }, { "Id": 1519, "CompName": "ZVV Test", "SEDOL": "SEDOL112", "ADP": "ADPS1133" } ]
顺便说一下,由于你的JSON是多态的(属性有时是对象的数组,有时只是对象),我认为反序列化为类层次结构或ExpandoObject
会更容易。
<强>更新强>
根据您更新的JSON,您可以使用SelectTokens()
和JSONPath recursive search operator ..
来查找第一个分析师的姓氏,其中递归搜索运算符处理分析师可能包含或不包含分析符的事实。阵列:
var compInfo = from issuer in feed.SelectTokens("DataFeed.Issuer").SelectMany(i => i.ObjectsOrSelf())
let security = issuer.SelectTokens("securities.Security").SelectMany(s => s.ObjectsOrSelf()).FirstOrDefault()
where security != null
select new
{
Id = (string)issuer["id"], // Change to (string)issuer["id"] if id is not necessarily numeric.
CompName = (string)issuer["name"],
SEDOL = (string)security["sedol"],
ADP = (string)security["customFields"]
.DescendantsAndSelf()
.OfType<JObject>()
.Where(o => (string)o["@name"] == "ADP Security Code")
.Select(o => o.SelectToken("values.value"))
.FirstOrDefault(),
Analyst = (string)security.SelectTokens("coverage.Coverage..analyst.@lastName").FirstOrDefault(),
};
答案 1 :(得分:1)
另请注意,您的JSON格式不正确。
创建的代理类无法找出安全类型,因为在一个实例中它是一个数组,而在另一个实例中它是一个简单的对象。
原始答案:
我使用json2csharp来帮助我获得一些课程,现在我可以使用这些类型:
var obj = JsonConvert.DeserializeObject<RootObject>(json);
var result = from a in obj.DataFeed.Issuer
select new
{
Sedol = a.securities.Security.sedol,
Name = a.name
};
类:
public class Values
{
public object value { get; set; }
}
public class CustomField
{
public string name { get; set; }
public string type { get; set; }
public Values values { get; set; }
}
public class CustomFields
{
public List<CustomField> customField { get; set; }
}
public class Security
{
public string id { get; set; }
public string sedol { get; set; }
public CustomFields customFields { get; set; }
}
public class Securities
{
public Security Security { get; set; }
}
public class Issuer
{
public string id { get; set; }
public string name { get; set; }
public string clientCode { get; set; }
public Securities securities { get; set; }
}
public class DataFeed
{
public string FeedName { get; set; }
public List<Issuer> Issuer { get; set; }
}
public class RootObject
{
public DataFeed DataFeed { get; set; }
}
答案 2 :(得分:0)
使用newtonsoft.json
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json);
我在我面前没有我的想法,但价值应该是:
obj.DataFeed.Issuer[0].securities.Security.sedol