【问题标题】:Get value from IEnumerable foreach loop从 IEnumerable foreach 循环中获取值
【发布时间】:2016-08-03 13:11:06
【问题描述】:

我需要从 JSON 文件创建一个 c# 对象,并且必须遵循以下工作解决方案:

JSON:

{
"AK": {
    "Anchorage": [{
        "Name": "John Doe",
        "Address": "123 Main St.",
        "City": "Anchorage",
        "State": "AK",
        "Zip": "12345"
    }],
    "Fairbanks": [{
        "Name": "Sally Smith",
        "Address": "987 Main St.",
        "City": "Fairbanks",
        "State": "AK",
        "Zip": "98765"
    }]
}
}

代码:

public class Location
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

// ------------------------------------------------------------------
string json = File.ReadAllText(@"C:json.txt");
dynamic deserialisedJson = JsonConvert.DeserializeObject(json);

var locations = new List<Location>();

foreach (var root in deserialisedJson)
{
    foreach (var state in root)
    {
        foreach (var city in state)
        {
            foreach (var location in city)
            {
                Location loc = new Location();
                loc.Name = location.First["Name"];
                loc.Address = location.First["Address"];
                loc.City = location.First["City"];
                loc.State = location.First["State"];
                loc.Zip = location.First["Zip"];
                locations.Add(loc);
            }
        }
    }
} 

但我需要将上述内容合并到 SSIS 包中,该包仅允许 .NET 3.5 及以下版本。下面这行代码需要.NET 4.0及以上:

dynamic deserialisedJson = JsonConvert.DeserializeObject(json);

我正在尝试通过使用 IEnumerable 来解决此限制,但我不确定如何获取所需值的语法?

string json = File.ReadAllText(@"C:json.txt");

var deserialisedJson = (IEnumerable)JsonConvert.DeserializeObject(json);

var locations = new List<Location>();

foreach (var root in deserialisedJson)
{
    foreach (var state in (IEnumerable)root)
    {
        foreach (var city in (IEnumerable)state)
        {
            foreach (var location in (IEnumerable)city)
            {
                Location loc = new Location();

                loc.Name = //What goes here???
                loc.Address = //What goes here???
                loc.City = //What goes here???
                loc.State = //What goes here???
                loc.Zip = //What goes here???

                locations.Add(loc);
            }
        }
    }
}

【问题讨论】:

  • 位置["姓名"] ?
  • 添加一个小json示例
  • 使用 location["Name"] 会出现错误:cannot apply indexing with [] to an expression of type 'object'
  • 而不是dynamic deserialisedJson = JsonConvert.DeserializeObject(json);ClassThatHasJsonStructure deserialisedJson = Json.Decode&lt;ClassThatHasJsonStructure&gt;(json) 在.Net3.5 中工作?
  • 你真的不需要类型。您可以以“动态”方式反序列化它。但是我们需要json的结构。

标签: c# .net json json.net


【解决方案1】:

这使用Linq to JSON 选择您想要的所有Location 对象:

var deserialisedJson = (IEnumerable)JsonConvert.DeserializeObject(json);
JObject jObj = JObject.Parse(json);

//Get all tokens that are under AK/(some descendant)/all items from collection
var result = jObj.SelectTokens("AK.*.[*]")
                    .Select(x => new Location
                    {
                        Name = x["Name"].Value<string>(),
                        Address = x["Address"].Value<string>(),
                        City = x["City"].Value<string>(),
                        State = x["State"].Value<string>(),
                        Zip = x["Zip"].Value<string>(),
                    }).ToList();

经过测试,这适用于 .Net 3.5 项目,其中包含适用于 .Net 的 Newtonsoft.Json

【讨论】:

  • @PixelPaul - 这对你有帮助吗?
【解决方案2】:

这是一个快速的解决方案:

var deserialized = JsonConvert.DeserializeObject<JObject>(json);
var locations = (
    from state in deserialized.Properties().Select(v => v.Value).OfType<JObject>()
    from city in state.Properties().Select(v => v.Value).OfType<JArray>()
    from location in city
    select new Location
    {
        Name = location.Value<string>("Name"),
        Address = location.Value<string>("Address"),
        City = location.Value<string>("City"),
        State = location.Value<string>("State"),
        Zip = location.Value<string>("Zip")
    }).ToList();

【讨论】:

    【解决方案3】:

    您可以使用 clases 让 newtonsoft 解决您的需求

    public class Location
    {
        public string Name { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Zip { get; set; }
    }
    public class AK
    {
        public Location[] Anchorage { get; set; }
        public Location[] Fairbanks { get; set; }
    }   
    
    
    var ak = JsonConvert.DeserializeObject<AK>(json);
    

    【讨论】:

    • 如果您需要它们在同一个列表中,只需将它们连接起来即可。 var locations = ak.Anchorage.Concat(ak.Fairbanks);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-31
    相关资源
    最近更新 更多