在C#中使用不在数组中的JSON元素

时间:2014-03-24 20:24:23

标签: c# json

我目前正在使用一个包含数组的源和不包含数组的源的JSON输出。

带数组的那个很简单,因为我可以创建一个表示对象和对象列表的类,然后遍历列表并获取每个对象的属性。但是,在没有数组的源代码中,它会让我循环。

我不知道如何迭代这个。好像我需要为“abc”和“def”创建单独的类,即使每个类的属性是相同的。有一种简单的方法可以做到这一点吗?

不包含数组的示例:

    {
"objectContainer": {
    "count": 25,
    "objects": {
        "abc": {
            "name": "object1",
            "parent": "0",
            "status": "0",
        },
        "def": {
            "name": "object2",
            "parent": "0",
            "status": "0",
        }
        etc....

提前感谢您的任何帮助。

3 个答案:

答案 0 :(得分:1)

您可以使用继承来防止重复" abc"和" def"一遍又一遍。

public class Base
{
    public string name { get; set; }
    public string parent { get; set; }
    public string status { get; set; }
}

public class Abc : Base { }

public class Def : Base { }

public class Objects
{
    public Abc abc { get; set; }
    public Def def { get; set; }
}

public class ObjectContainer
{
    public int count { get; set; }
    public Objects objects { get; set; }
}

public class RootObject
{
    public ObjectContainer objectContainer { get; set; }
}

然后使用JSON.NET,您可以反序列化字符串。

var root = JsonConvert.DeserializeObject<RootObject>( json );

问题是你每次在那里得到一个新对象时都需要更改代码(例如ghi)。

另一个选项,特别是如果您要显示不同的对象名称,将只是自己串行解析JSON。

JsonTextReader reader = new JsonTextReader( new StringReader( json ) );
while( reader.Read() )
{
    if( reader.Value != null )
    {
        Console.WriteLine( "Field: {0}, Value: {1}", reader.TokenType, reader.Value );
    }
}

显然,在将输出写入控制台的位置,您必须检查TokenType和Value并将其填充到对象中。

<强>更新

这非常难看,但我很好奇我如何将其解析为对象结构。您需要稍微更改接收对象定义。

public class Base
{
    public string name { get; set; }
    public string parent { get; set; }
    public string status { get; set; }
}

public class Objects
{
    public List<Base> bases { get; set; }

    public Objects()
    {
        bases = new List<Base>();
    }
}

public class ObjectContainer
{
    public int count { get; set; }
    public Objects objects { get; set; }

    public ObjectContainer()
    {
        objects = new Objects();
    }
}

public class RootObject
{
    public ObjectContainer objectContainer { get; set; }

    public RootObject()
    {
        objectContainer = new ObjectContainer();
    }
}

然后你可以使用以下方法解析它:

while( reader.Read() )
{
    if( reader.Value != null )
    {
        switch( reader.Depth )
        {
            case 2:
                if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "count" )
                {
                    reader.Read();
                    root.objectContainer.count = Convert.ToInt32( reader.Value );
                }
                break;

            case 3:
                newBase = new Base();
                root.objectContainer.objects.bases.Add( newBase );
                break;

            case 4:
                if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "name" )
                {
                    reader.Read();
                    newBase.name = reader.Value.ToString();
                }
                if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "parent" )
                {
                    reader.Read();
                    newBase.parent = reader.Value.ToString();
                }
                if( reader.TokenType == JsonToken.PropertyName && reader.Value.ToString() == "status" )
                {
                    reader.Read();
                    newBase.status = reader.Value.ToString();
                }
                break;
        }
    }
}

这不是世界上最漂亮的代码,但只要JSON的结构没有改变,你最终会得到一个漂亮的对象模型,无论有多少个子对象或它们的名字是什么。< / p>

答案 1 :(得分:0)

根据您上面的JSON,您可能需要为这些对象创建类。您也可以使用继承来抽象一些。如果可能的话,将“对象”作为一个数组更有意义,因为您不需要创建单独的对象。名称和实现都表明了一个数组。

如果您无法更改JSON的结构,请查看http://json.org/页面底部的不同库。有些可能比其他人更有帮助。 Json.NET是我经常使用的,你可以使用像他们的JSonReader这样的东西获得更好的结果,所以你不必创建一个过于复杂的对象结构。

答案 2 :(得分:0)

您可以使用JObject中的优秀(和动态)JSON.NET library类,如下所示:

// example input
var json = @"{""objectContainer"": {
""count"": 25,
""objects"": {
    ""abc"": {
        ""name"": ""object1"",
        ""parent"": ""0"",
        ""status"": ""0"",
    },
    ""def"": {
        ""name"": ""object2"",
        ""parent"": ""0"",
        ""status"": ""0"",
    }
}}";

var obj = JsonConvert.DeserializeObject(json);
var objectContainer = ((JObject)obj)["objectContainer"];
var abc = objectContainer["objects"]["abc"];
Console.WriteLine(abc["name"]);

输出结果为:

  

OUTPUT1

您甚至可以直接使用JObject.Parse() method来加载和解析JSON代码部分(例如,如果您只能从完整的JSON字符串中提取abc部分):

var abc = JObject.Parse(@"{""abc"": {
        ""name"": ""object1"",
        ""parent"": ""0"",
        ""status"": ""0"",
    }}")["abc"];
    Console.WriteLine(abc["name"]);

var abcd = JObject.Parse(@"{
        ""name"": ""object1"",
        ""parent"": ""0"",
        ""status"": ""0"",
    }");
    Console.WriteLine(abcd["name"]);

然后,您可以将提取的值分配给自定义类。

使用库和JObject类,您不需要用类来表示JSON。缺点是,您没有类的安全性及其属性。


<强>更新

您可以在不知道名称的情况下迭代属性/对象:

var obj = JsonConvert.DeserializeObject(json);
var objectContainer = ((JObject)obj)["objectContainer"];
foreach (var o in objectContainer["objects"])
{
    if (o is JProperty)
    {
        var op = ((JProperty)o);
        Console.WriteLine("{0} - {1}", op.Name, op.Value);
    }
}

输出结果为:

abc - {
"name": "object1",
"parent": "0",
"status": "0"
}
def - {
"name": "object2",
"parent": "0",
"status": "0"
}