簡體   English   中英

使用C#中不在數組中的JSON元素

[英]Consuming JSON elements in C# that are not in an array

我目前正在從一個包含數組的源中使用JSON輸出,而另一個不包含數組。

具有數組的對象很簡單,因為我可以創建一個代表對象和對象列表的類,然后遍歷該列表並獲取每個對象的屬性。 但是,在沒有數組的源代碼中,它使我陷入循環。

我不知道該如何迭代。 似乎我需要為“ abc”和“ def”創建單獨的類,即使每個類的屬性都相同。 有沒有簡單的方法可以做到這一點?

不包含數組的示例:

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

在此先感謝您的協助。

您可以使用繼承來防止一遍又一遍地重復“ 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的結構不變,無論有多少個子對象或它們的名稱是什么,您都會得到一個不錯的對象模型。

根據上面的JSON,您可能需要為這些對象創建類。 您也可以通過繼承將其中的一些抽象出來。 如果可能的話,將“對象”作為一個數組將更有意義,因為您無需創建單獨的對象。 名稱和實現都建議使用數組。

如果您無法更改JSON的結構,請在頁面底部的http://json.org/中查看不同的庫。 有些可能比其他的更有幫助。 Json.NET是我通常使用的那種,使用諸如JSonReader之類的東西可能會獲得更好的結果,因此您不必創建過於復雜的對象結構。

您可以使用JSON.NET庫中出色的(動態) JObject類,如下所示:

// 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()方法僅加載和解析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"
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM