如何访问(排序)复杂json对象中的属性?

时间:2017-09-20 18:44:00

标签: c# json

我试图获取某个(某种程度上)复杂的json对象的属性但是没有运气。

json对象本身看起来像这样,是从查询生成的:

{
 "displayFieldName": "REPNAME",
 "fieldAliases": {
  "DISTRICT": "DISTRICT",
  "REPNAME": "REPNAME"
 },
 "fields": [
  {
   "name": "DISTRICT",
   "type": "esriFieldTypeDouble",
   "alias": "DISTRICT"
  },
  {
   "name": "REPNAME",
   "type": "esriFieldTypeString",
   "alias": "REPNAME",
   "length": 150
  }
 ],
 "features": [
  {
   "attributes": {
    "DISTRICT": 21,
    "REPNAME": "Ira Anders"
   }
  }
 ]
}

我去了json2csharp.com从那个json生成C#类并得到了这个:

public class FieldAliases
{
    public string DISTRICT { get; set; }
    public string REPNAME { get; set; }
}

public class Field
{
    public string name { get; set; }
    public string type { get; set; }
    public string alias { get; set; }
    public int? length { get; set; }
}

public class Attributes
{
    public int DISTRICT { get; set; }
    public string REPNAME { get; set; }
}

public class Feature
{
    public Attributes attributes { get; set; }
}

public class RootObject
{
    public string displayFieldName { get; set; }
    public FieldAliases fieldAliases { get; set; }
    public List<Field> fields { get; set; }
    public List<Feature> features { get; set; }
}

我试图了解&#34;属性&#34;对象并让它返回DISTRICT和REPNAME(应该是21和Ira Anders)。我已经尝试了以下方法:

使用DataContractJsonSerializer类 - 已尝试过3种或4种不同的方法来执行此操作,但它仍然无法正常工作

Attributes attr = new Attributes();
MemoryStream stream1 = new MemoryStream(Encoding.UTF8.GetBytes(MoRepjson));
stream1.Position = 0;
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(Attributes));
attr = deserializer.ReadObject(stream1) as Attributes;
string dist = attr.DISTRICT.ToString();
string repname = attr.REPNAME;
stream1.Close();

我还尝试过javaScriptSerializer类,它也不起作用:

JavaScriptSerializer ser = new JavaScriptSerializer();
Attributes attr = ser.Deserialize<Attributes>(MoRepjson);
string dist = attr.DISTRICT.ToString();
string repname = attr.REPNAME;

然后使用JSON.NET库 - 不再工作:

Attributes attr = JsonConvert.DeserializeObject<Attributes>(MoRepjson);
string dist = attr.DISTRICT.ToString();
string repname = attr.REPNAME;

字符串&#34; dist&#34;和&#34; repname&#34;变量在我的网页上。出于某种原因,当我运行它时,DISTRICT通常会显示&#34; 0&#34; (正如我上面的json所示它应该显示21)。不知道它在哪里或如何变为零。 REPNAME变量显示空白。

如果我创建一个令人头脑麻木的简单json对象硬编码对象,如...

Attributes attr = new Attributes { DISTRICT = 9999, REPNAME = "Some Representative" };

...访问DISTRICT和REPNAME(例如repname = attr.REPNAME)没问题。只有当我尝试访问我的实际/真正的json时才会遇到问题。

我唯一能做的事情就是工作&#34;是通过访问RootObject,如...

RootObject ro = JsonConvert.DeserializeObject<RootObject>(MoRepjson);
string test = ro.displayFieldName;

...正确显示&#34; REPNAME&#34; (虽然我不确定为什么它会显示REPNAME而不是DISTRICT)。但是,如果我尝试通过做类似的事情来深入了解整个json对象。

RootObject ro = JsonConvert.DeserializeObject<RootObject>(MoRepjson);
string test = ro.features.???

......我碰到了一堵砖墙。只是为了它,我试图替换......

public List<Feature> features { get; set; }

...在我的RootObject中......

public Feature features { get; set; }

......但这也不起作用。

我实际上并不关心除属性之外的其他类,但是当我尝试直接访问Attributes对象时,它会变空。一旦我也得到了(正确的)&#34; 1&#34;当我得到RootObject的数量时,所以我知道它已经返回某些东西,我只是不知道如何实现它。

任何帮助将不胜感激。谢谢!

4 个答案:

答案 0 :(得分:0)

听起来MoRepjson是您发布的Json。由于它表示RootObject,因此必须将其反序列化为RootObject。将其反序列化为其他任何东西都没有意义。

其次,你得到的是一个完整的MoRepjson对象。其中包含List<>个功能。你可以访问这样的个人。

RootObject ro = JsonConvert.DeserializeObject<RootObject>(MoRepjson);
List<Feature> features = ro.features;
Feature firstFeature = features[0];
Attributes attributes = firstFeature.attributes;
string repname = attributes.REPNAME;

上面是简单的代码,用于演示由Json产生的对象的结构。在实践中,你会做这样的事情。

var rootObject = JsonConvert.DeserializeObject<RootObject>(MoRepjson);

var firstAttributes rootObject.features
    .Select(x => x.attributes)
    .FirstOrDefault();

if(firstAttributes != null)
{
    string repName = firstAttributes.REPNAME;
    int district = firstAttributes.DISTRICT;
}

答案 1 :(得分:0)

您的代码无效的原因是您有一个带有features列表的根对象,其中每个Feature都有attributes属性。

如果您只想要所有属性,请使用以下内容:

RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(MoRepjson);
var attributes = rootObject.features.Select(f => f.attributes);

foreach (var a in attributes)
{
    Console.WriteLine("DISTRICT: " + a.DISTRICT);
    Console.WriteLine("REPNAME: " + a.REPNAME);
}

在此测试:https://dotnetfiddle.net/CliXDW

答案 2 :(得分:0)

如果您只想要一个特定的值,使用JSON.NET要简单得多:

string json = ...
var root = JObject.Parse(json);
var fieldAliases = root["fieldAliases"];
string district = fieldAliases["DISTRICT"].Value<string>();
string repName  = fieldAliases["REPNAME"].Value<string>();

答案 3 :(得分:0)

感谢。现在我又收到了另一个错误,而且似乎并没有出现。似乎正在发生上面发布的两个解决方案。它只在运行时产生错误,而不是构建错误:

编译器错误消息:CS0101:命名空间''已经包含'Attributes'的定义

然后它指向两行:

public class Attributes

public int DISTRICT { get; set; }

但它并没有一直突然出现,我不会做任何改变,但突然间它会起作用。