ยกเลิกการทำให้วัตถุ json เป็นวัตถุแบบไดนามิกโดยใช้ Json.net


426

เป็นไปได้หรือไม่ที่จะส่งคืนออบเจ็กต์แบบไดนามิกจากการดีซีเรียลไลซ์เจสันด้วย json.net ฉันต้องการทำสิ่งนี้:

dynamic jsonResponse = JsonConvert.Deserialize(json);
Console.WriteLine(jsonResponse.message);

1
พิจารณาที่จะสร้างคลาส C # จาก JSON json2csharp.comและใช้คลาสที่สร้างขึ้นแทนไดนามิก
Michael Freidgeim


คุณจะแนะนำ stackOverflow ปิดคำถามว่า "เก่าเกินไป" ได้อย่างไร เป็นเวลาหกปีแล้วที่มีคำตอบที่ถูกต้องและคำแนะนำที่สมเหตุสมผลสำหรับ. net ทุกรุ่นตั้งแต่นั้นมา ... มากมายที่พวกเขาไม่ได้เป็นประโยชน์อีกต่อไป
andrew lorien

คำตอบ:


546

Json.NET ช่วยให้เราสามารถทำสิ่งนี้:

dynamic d = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}");

Console.WriteLine(d.number);
Console.WriteLine(d.str);
Console.WriteLine(d.array.Count);

เอาท์พุท:

 1000
 string
 6

เอกสารที่นี่: LINQ ถึง JSON ด้วย Json.NET

ดูเพิ่มเติมJObject.ParseและJArray.Parse


36
JArray.Parseโปรดทราบว่าสำหรับอาร์เรย์ไวยากรณ์คือ
jgillich

4
ทำไมเราต้องใช้คำไดนามิก? ฉันกลัวไม่เคยใช้มาก่อน: D
MonsterMMORPG

3
ใน VB.Net ที่คุณต้องทำDim d As Object = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}")
ilans

2
@ มอนสเตอร์ MMORPG คุณควรเป็น :) Dynamic เป็นรูปแบบการต่อต้านในเกือบทุกสถานการณ์ แต่ทุกขณะนี้คุณอาจมีสถานการณ์ที่เหมาะสมที่จะใช้
Pluc

4
ด้วย Newtonsoft.Json 8.0.3 (.NET 4.5.2): Microsoft.CSharp.RuntimeBinder.RuntimeBinderException เกิดขึ้น HResult = -2146233088 ข้อความ = 'Newtonsoft.Json.Linq.JObject' ไม่มีคำจำกัดความสำหรับ 'number' Source = Microsoft .CSharp StackTrace: ที่ Microsoft.CSharp.RuntimeBinder.RuntimeBinderController.SubmitError (CError pError)
4698855

107

ตั้งแต่ Json.NET 4.0 รีลีส 1 มีการรองรับแบบไดนามิกเนทีฟ:

[Test]
public void DynamicDeserialization()
{
    dynamic jsonResponse = JsonConvert.DeserializeObject("{\"message\":\"Hi\"}");
    jsonResponse.Works = true;
    Console.WriteLine(jsonResponse.message); // Hi
    Console.WriteLine(jsonResponse.Works); // True
    Console.WriteLine(JsonConvert.SerializeObject(jsonResponse)); // {"message":"Hi","Works":true}
    Assert.That(jsonResponse, Is.InstanceOf<dynamic>());
    Assert.That(jsonResponse, Is.TypeOf<JObject>());
}

และแน่นอนว่าวิธีที่ดีที่สุดในการรับเวอร์ชันปัจจุบันคือผ่าน NuGet

อัปเดตเมื่อวันที่ 11/12/2557 เพื่อแสดงความคิดเห็น:

มันใช้งานได้ดีอย่างสมบูรณ์แบบ หากคุณตรวจสอบชนิดในการดีบักที่คุณจะเห็นว่ามีค่าเป็นในความเป็นจริงแบบไดนามิก ประเภทพื้นฐานJObjectเป็น หากคุณต้องการควบคุมประเภท (เช่นการระบุExpandoObjectให้ทำเช่นนั้น

ป้อนคำอธิบายรูปภาพที่นี่


20
ดูเหมือนว่ามันจะไม่ทำงาน มันจะส่งกลับเฉพาะ JObject ไม่ใช่ตัวแปรแบบไดนามิก
พอล

12
BTW ใช้งานได้: JsonConvert.DeserializeObject <ขยายoObject> (STRING); กับ deserialization ที่เหมาะสมเพื่อให้เราไม่ได้มี JObject ฯลฯ
Gutek

2
@Gutek ไม่แน่ใจว่าปัญหาของคุณคืออะไร คุณเรียกใช้รหัสหรือไม่ ฉันเพิ่มการยืนยันในการทดสอบและเพิ่มคุณสมบัติที่ไม่ได้อยู่ใน json ดั้งเดิม ภาพหน้าจอของตัวดีบักรวมอยู่ด้วย
David Peden

1
@DavidPeden ถ้าคุณมี JObject และคุณจะพยายามผูกมันไว้ใน Razor คุณจะได้รับการยกเว้น คำถามเกี่ยวกับการดีซีเรียลไลซ์ให้กับวัตถุแบบไดนามิก - JObject เป็นแบบไดนามิก แต่มีประเภท "ของตัวเอง" เช่น JValue ไม่ใช่ประเภทดั้งเดิม ฉันไม่สามารถใช้@Model.Propชื่อในมีดโกนได้หากประเภทส่งคืนคือ JValue
Gutek

2
งานนี้ JValueแต่คุณสมบัติแบบไดนามิกแต่ละคนเป็น สิ่งที่ทำให้ฉันสับสนเพราะฉันทำงานในหน้าต่างดีบั๊กเกอร์ / ทันทีและไม่เห็นเพียงstrings เดวิดแสดงภาพหน้าจอด้านล่าง JValueเป็นแปลงสภาพดังนั้นคุณก็สามารถทำstring m = jsonResponse.message
ลุค Puplett

66

หากคุณเพียง แต่ลังเลที่จะเปลี่ยนคุณจะได้รับ JObject กลับมา คุณสามารถได้รับสิ่งที่คุณต้องการโดยใช้ ExpandoObject

var converter = new ExpandoObjectConverter();    
dynamic message = JsonConvert.DeserializeObject<ExpandoObject>(jsonString, converter);

1
ผลลัพธ์ยังสามารถแปลงเป็นพจนานุกรม
FindOutIslamNow

1
สิ่งที่ฉันมองหา! ขอบคุณ!
DarkDeny

42

ฉันรู้ว่านี่เป็นโพสต์เก่า แต่จริงๆแล้ว JsonConvert มีวิธีการที่แตกต่างกันดังนั้นมันจะเป็น

var product = new { Name = "", Price = 0 };
var jsonResponse = JsonConvert.DeserializeAnonymousType(json, product);

23
นั่นจะเป็นการดีซีเรียลไลซ์เพย์โหลด json เป็นประเภทไม่ระบุชื่อไม่ใช่ประเภทไดนามิก ประเภทไม่ระบุชื่อและประเภทไดนามิกเป็นสิ่งที่แตกต่างกันและฉันไม่เชื่อว่าที่อยู่นี้ถามคำถาม
jrista

1
จำเป็นต้องใช้สองตัวแปรหรือไม่? ทำไมไม่ลองใช้อันแรกในประโยคที่สอง?
RenniePet

21

ใช่คุณสามารถทำได้โดยใช้ JsonConvert.DeserializeObject ในการทำเช่นนั้นทำได้ง่ายๆเพียง:

dynamic jsonResponse = JsonConvert.DeserializeObject(json);
Console.WriteLine(jsonResponse["message"]);

1
JsonConvertDeserializeไม่ได้มีวิธีการที่เรียกว่า
Can Poyrazoğlu

มันควรจะเป็น DeserializeObject แต่นี่ควรเป็นคำตอบที่ได้รับการยอมรับ IMO
superjugy

21

หมายเหตุ:ในเวลาที่ฉันตอบคำถามนี้ในปี 2010 ไม่มีวิธีใดที่จะทำการดีซีเรียลไลซ์โดยไม่มีประเภทใด ๆ สิ่งนี้ทำให้คุณสามารถ deserialize โดยไม่ต้องไปกำหนดคลาสจริงและอนุญาตให้คลาสที่ไม่ระบุชื่อทำการ deserialization


คุณต้องมีประเภทของประเภทที่จะทำการยกเลิก คุณสามารถทำบางสิ่งตามแนวของ:

var product = new { Name = "", Price = 0 };
dynamic jsonResponse = JsonConvert.Deserialize(json, product.GetType());

คำตอบของฉันขึ้นอยู่กับโซลูชันสำหรับการสร้างของ. NET 4.0 ใน JSON serializer ลิงก์ไปยัง deserialize เป็นประเภทที่ไม่ระบุตัวตนอยู่ที่นี่:

http://blogs.msdn.com/b/alexghi/archive/2008/12/22/using-anonymous-types-to-deserialize-json-data.aspx


ฉันอยู่กับคุณฟิลล์ไม่รู้ว่าทำไมคนอื่นถึงลงคะแนนในเรื่องนี้ถ้ามีคนช่วยได้โปรดอธิบายหน่อยได้ไหม
PEO

18
พวกเขากำลัง downvoting เนื่องจากคำถามเกี่ยวกับการดีซีเรียลไลซ์โดยไม่มีประเภท
richard

4
คำตอบนั้นใช้ได้ในขณะที่เขียนในปี 2010 เมื่อไม่มีวิธีแก้ไขปัญหาอื่น มันเป็นคำตอบที่ได้รับการยอมรับเป็นระยะเวลาหนึ่งจนกระทั่งการสนับสนุนมาใน JSON.NET
Phill

1
สิ่งนี้ไม่ได้สร้างวัตถุแบบไดนามิก สิ่งนี้จะสร้าง JObject ที่คุณอ้างอิงว่าเป็นไดนามิก แต่มันยังคงเป็น JObject อยู่ภายใน
ghostbust555

5

หากคุณใช้ JSON.NET กับเวอร์ชันเก่าซึ่งไม่ได้เป็น JObject

นี่เป็นอีกวิธีง่ายๆในการสร้างวัตถุแบบไดนามิกจาก JSON: https://github.com/chsword/jdynamic

NuGet ติดตั้ง

PM> Install-Package JDynamic

สนับสนุนการใช้ดัชนีสตริงเพื่อเข้าถึงสมาชิกเช่น:

dynamic json = new JDynamic("{a:{a:1}}");
Assert.AreEqual(1, json["a"]["a"]);

กรณีทดสอบ

และคุณสามารถใช้ util นี้ดังต่อไปนี้:

รับค่าโดยตรง

dynamic json = new JDynamic("1");

//json.Value

2. รับสมาชิกในวัตถุ json

dynamic json = new JDynamic("{a:'abc'}");
//json.a is a string "abc"

dynamic json = new JDynamic("{a:3.1416}");
//json.a is 3.1416m

dynamic json = new JDynamic("{a:1}");
//json.a is integer: 1

3.IEnumerable

dynamic json = new JDynamic("[1,2,3]");
/json.Length/json.Count is 3
//And you can use json[0]/ json[2] to get the elements

dynamic json = new JDynamic("{a:[1,2,3]}");
//json.a.Length /json.a.Count is 3.
//And you can use  json.a[0]/ json.a[2] to get the elements

dynamic json = new JDynamic("[{b:1},{c:1}]");
//json.Length/json.Count is 2.
//And you can use the  json[0].b/json[1].c to get the num.

อื่น ๆ

dynamic json = new JDynamic("{a:{a:1} }");

//json.a.a is 1.

2

ใช่มันเป็นไปได้ ฉันทำมาตลอด

dynamic Obj = JsonConvert.DeserializeObject(<your json string>);

มันค่อนข้างยากสำหรับคนที่ไม่ใช่เจ้าของภาษา สมมติว่าภายใน Obj ของคุณมีวัตถุ ClassA และ ClassB พวกเขาทั้งหมดถูกแปลงเป็น JObject สิ่งที่คุณต้องทำคือ:

ClassA ObjA = Obj.ObjA.ToObject<ClassA>();
ClassB ObjB = Obj.ObjB.ToObject<ClassB>();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.