Giải phóng đối tượng json thành đối tượng động bằng Json.net


426

Có thể trả về một đối tượng động từ quá trình khử tuần hoàn json bằng json.net không? Tôi muốn làm một cái gì đó như thế này:

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

1
Xem xét để tạo lớp C # từ JSON json2csharp.com và sử dụng lớp được tạo thay vì động
Michael Freidgeim


Làm thế nào để bạn đề xuất stackOverflow đóng một câu hỏi là "quá cũ"? Đã sáu năm, có câu trả lời hợp lệ và đề xuất hợp lý cho mọi phiên bản .net kể từ đó ... rất nhiều điều mà chúng không thực sự hữu ích nữa.
rút lorien

Câu trả lời:


546

Json.NET cho phép chúng tôi làm điều này:

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);

Đầu ra:

 1000
 string
 6

Tài liệu ở đây: LINQ to JSON với Json.NET

Xem thêm JObject.PudeJArray.Pude


36
Lưu ý rằng đối với mảng cú pháp là JArray.Parse.
jgillich

4
Tại sao chúng ta cần sử dụng từ động? tôi sợ chưa từng sử dụng trước đây: D
MonsterMMORPG

3
Trong VB.Net bạn cần làmDim d As Object = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}")
ilans 31/12/14

2
@MonsterMMORPG Bạn nên :) Động là một kiểu chống trong hầu hết mọi trường hợp, nhưng, mọi lúc, bạn có thể gặp tình huống sử dụng nó hợp lý.
Pluc 18/03/2016

4
Với Newtonsoft.Json 8.0.3 (.NET 4.5.2): Microsoft.CSharp. .CSharp StackTrace: tại Microsoft.CSharp.RuntimeBinder.RuntimeBinderController.SubmitError (CError pError)
user4698855

107

Kể từ phiên bản 1 của Json.NET 4.0, có hỗ trợ động riêng:

[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>());
}

Và, tất nhiên, cách tốt nhất để có được phiên bản hiện tại là thông qua NuGet.

Cập nhật (11/12/2014) để giải quyết ý kiến:

Điều này hoạt động hoàn toàn tốt. Nếu bạn kiểm tra loại trong trình gỡ lỗi, bạn sẽ thấy rằng giá trị thực tế là động . Các loại cơ bản là một JObject. Nếu bạn muốn kiểm soát loại (như chỉ định ExpandoObject, thì hãy làm như vậy.

nhập mô tả hình ảnh ở đây


20
Điều này dường như không bao giờ làm việc. Nó chỉ trả về một JObject, không phải là một biến động.
Paul

12
BTW, cái này hoạt động: JsonConvert.DeserializeObject <ExpandoObject> (STRING); với quá trình khử lưu huỳnh thích hợp, vì vậy chúng tôi không có JObject, v.v.
Gutek

2
@Gutek không chắc vấn đề của bạn là gì. Bạn đã chạy mã? Tôi đã thêm các xác nhận vào thử nghiệm và thêm một thuộc tính không có trong json ban đầu. Ảnh chụp màn hình của trình gỡ lỗi bao gồm.
David Peden

1
@DavidPeden nếu bạn có JObject và bạn sẽ cố gắng ràng buộc rằng trong Dao cạo bạn sẽ có ngoại lệ. Câu hỏi là về việc khử lưu huỳnh cho đối tượng động - JObject là động nhưng chứa các kiểu "riêng" như JValue chứ không phải kiểu nguyên thủy. Tôi không thể sử dụng @Model.Proptên trong Dao cạo nếu loại trả về là JValue.
Gutek

2
Điều này hoạt động, nhưng mỗi thuộc tính động là một JValue. Điều này làm tôi bối rối vì tôi đang làm việc trong trình gỡ lỗi / cửa sổ ngay lập tức và không thấy chỉ là strings. David cho thấy điều này trong ảnh chụp màn hình dưới cùng. Có thể JValuechuyển đổi để bạn có thể thực hiệnstring m = jsonResponse.message
Luke Puplett 7/215

66

Nếu bạn chỉ khử lưu động thành năng động, bạn sẽ nhận lại được JObject. Bạn có thể nhận được những gì bạn muốn bằng cách sử dụng ExpandoObject.

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

1
Kết quả cũng có thể được chuyển đổi thành một từ điển
FindOutIslamNow

1
Chính xác những gì tôi tìm kiếm! Cảm ơn!
DarkDeny

42

Tôi biết đây là bài viết cũ nhưng JsonConvert thực sự có một phương pháp khác vì vậy nó sẽ là

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

23
Điều đó sẽ được khử lưu lượng tải trọng json thành một loại ẩn danh, không phải là một loại động. Các loại ẩn danh và các loại động là những thứ khác nhau và tôi không tin điều này giải quyết câu hỏi được hỏi.
jrista

1
Có cần thiết phải sử dụng hai biến? Tại sao không sử dụng lại cái đầu tiên trong câu lệnh thứ hai?
RenniePet

21

Có, bạn có thể làm điều đó bằng cách sử dụng JsonConvert.DeserializeObject. Để làm điều đó, chỉ cần làm đơn giản:

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

1
JsonConvertkhông chứa một phương thức gọi là Deserialize.
Có thể Poyrazoğlu

nó chỉ nên là DeserializeObject, nhưng đây phải là câu trả lời được chấp nhận IMO
superjugy

21

Lưu ý: Tại thời điểm tôi trả lời câu hỏi này vào năm 2010, không có cách nào để giải tuần tự hóa mà không có loại nào, điều này cho phép bạn giải tuần tự hóa mà không cần phải xác định lớp thực tế và cho phép một lớp ẩn danh được sử dụng để thực hiện khử lưu huỳnh.


Bạn cần phải có một số loại để khử lưu huỳnh. Bạn có thể làm một cái gì đó dọc theo dòng:

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

Câu trả lời của tôi dựa trên một giải pháp cho bản dựng tuần tự JSON của .NET 4.0. Liên kết để khử lưu lượng đến các loại ẩn danh ở đây:

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


Tôi với bạn phill không biết tại sao mọi người bỏ phiếu này, nếu có ai có thể vui lòng .. vui lòng giải thích tại sao?
PEO

18
Họ đang bỏ phiếu vì câu hỏi là về khử lưu huỳnh mà không có loại.
Richard

4
Câu trả lời có giá trị tại thời điểm viết nó vào năm 2010 khi không có giải pháp nào khác. Nó thậm chí còn là câu trả lời được chấp nhận trong một khoảng thời gian nhỏ cho đến khi có hỗ trợ trong JSON.NET.
Phill

1
Điều này không tạo ra một đối tượng năng động. Điều này tạo ra một JObject mà bạn tham chiếu như một động. Nhưng nó vẫn là một JObject bên trong.
ghostbust555

5

Nếu bạn sử dụng JSON.NET với phiên bản cũ không JObject.

Đây là một cách đơn giản khác để tạo một đối tượng động từ JSON: https://github.com/chsword/jdynamic

Cài đặt NuGet

PM> Install-Package JDynamic

Hỗ trợ sử dụng chỉ mục chuỗi để truy cập thành viên như:

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

Trường hợp thử nghiệm

Và bạn có thể sử dụng tiện ích này như sau:

Nhận giá trị trực tiếp

dynamic json = new JDynamic("1");

//json.Value

2.Nhận thành viên trong đối tượng 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. vô số

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.

Khác

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

//json.a.a is 1.

2

Vâng, nó là có thể. Tôi đã làm điều đó trong suốt thời gian đó.

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

Nó là một chút phức tạp hơn cho loại không bản địa. Giả sử bên trong Obj của bạn, có các đối tượng ClassA và ClassB. Tất cả đều được chuyển đổi thành JObject. Những gì bạn cần làm là:

ClassA ObjA = Obj.ObjA.ToObject<ClassA>();
ClassB ObjB = Obj.ObjB.ToObject<ClassB>();
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.