[英]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.