2008-10-14 40 views
8

Vì Trình khởi tạo đối tượng rất giống với JSON, và bây giờ có các kiểu ẩn danh trong .NET. Sẽ rất tuyệt khi có thể lấy một chuỗi, chẳng hạn như JSON và tạo một đối tượng ẩn danh đại diện cho chuỗi JSON.Bạn có thể khởi tạo một đối tượng đối tượng từ JSON trong .NET không?

Sử dụng Object Initializers để tạo ra một loại Anonymous:

var person = new { 
    FirstName = "Chris", 
    LastName = "Johnson" 
}; 

Nó sẽ là tuyệt vời nếu bạn có thể vượt qua trong một chuỗi đại diện của đối tượng đang Initializer (tốt hơn là một cái gì đó giống như JSON) để tạo ra một thể hiện của một Anonymous Nhập với dữ liệu đó.

Tôi không biết nếu nó có thể, vì C# là không động, và trình biên dịch thực sự chuyển đổi Object Initializer một d Anonymous Type into strongly typed code that can run. This is explained in bài viết này.

Có thể chức năng lấy JSON và tạo từ khóa/giá trị với nó sẽ hoạt động tốt nhất.

Tôi biết bạn có thể tuần tự hóa/deserializer một đối tượng thành JSON trong .NET, nhưng những gì tôi tìm là một cách để tạo một đối tượng cơ bản được nhập sai, tương tự như cách JavaScript hoạt động.

Có ai biết giải pháp tốt nhất để thực hiện việc này trong .NET không?

CẬP NHẬT: Làm sáng tỏ bối cảnh tại sao tôi hỏi điều này ... Tôi đã suy nghĩ về cách C# hỗ trợ JSON tốt hơn ở cấp độ ngôn ngữ (có thể) và tôi đang cố gắng nghĩ cách hôm nay, vì lý do khái niệm. Vì vậy, tôi nghĩ rằng tôi muốn đăng nó ở đây để bắt đầu một cuộc thảo luận.

Trả lời

6

Có những ngôn ngữ cho .NET có vịt-gõ nhưng nó không thể với C# sử dụng Dot.Notation từ C# đòi hỏi rằng tất cả các tài liệu tham khảo thành viên được giải quyết tại thời gian biên dịch. Nếu bạn muốn sử dụng Dot.Notation, bạn vẫn phải định nghĩa một lớp ở đâu đó với các thuộc tính bắt buộc và sử dụng bất kỳ phương thức nào bạn muốn khởi tạo lớp từ dữ liệu JSON.Việc xác định trước một lớp không có các lợi ích như nhập mạnh, hỗ trợ IDE bao gồm intellisense và không phải lo lắng về lỗi chính tả. Bạn vẫn có thể sử dụng các loại vô danh:

T deserialize<T>(string jsonStr, T obj) { /* ... */} 

var jsonString = "{FirstName='Chris', LastName='Johnson, Other='unused'}"; 
var person  = deserialize(jsonString, new {FirstName="",LastName=""}); 
var x   = person.FirstName; //strongly-typed 
+0

+1, dơ bẩn, nhưng hiện tại là cách duy nhất để làm những gì mà OP muốn. – user7116

+0

Rất đẹp, đó là một cách tôi không nghĩ đến. –

+0

câu trả lời sẽ là gì kể từ bây giờ C# hỗ trợ các loại động –

0

Ứng dụng này là gì?

Tôi sẽ không đi xuống con đường này vì một vài lý do.

  • Đầu tiên; nó có thể yêu cầu rất nhiều mã hỗ trợ sử dụng sự phản chiếu và như vậy để tạo ra phương thức minh bạch mà bạn đang nói đến.

  • Thứ hai, như bạn đã nói, C# là ngôn ngữ được nhập mạnh mẽ và những thứ như thế này bị bỏ sót trong đặc tả ngôn ngữ vì lý do.

  • Thứ ba, chi phí để thực hiện việc này sẽ không đáng giá. Hãy nhớ rằng các trang web (đặc biệt là các truy vấn AJAX) nên thực sự nhanh hoặc nó đánh bại mục đích. Nếu bạn đi trước và chi tiêu 50% serializing các đối tượng của bạn giữa C# và Javascript thì bạn có một vấn đề.

Giải pháp của tôi là tạo một lớp chỉ gói gọn từ điển và nhận chuỗi JSON làm đối số ctor. Sau đó, chỉ cần mở rộng lớp đó cho từng loại truy vấn JSON bạn muốn xử lý. Đây sẽ là giải pháp mạnh mẽ và nhanh hơn nhưng vẫn duy trì khả năng mở rộng và dễ sử dụng. Nhược điểm là có nhiều mã để viết cho mỗi loại yêu cầu JSON.

:)

5

Bạn nên kiểm tra JSON.net dự án:

http://james.newtonking.com/pages/json-net.aspx

bạn về cơ bản nói về khả năng hydrat hóa một đối tượng từ JSON, mà điều này sẽ làm. Nó sẽ không làm các kiểu ẩn danh, nhưng có thể nó sẽ giúp bạn đủ gần.

1

Bạn không thể trả về loại ẩn danh từ phương thức **, do đó, sự tồn tại của loại ẩn danh "được bù lại" sẽ bị giới hạn ở phương pháp được bù nước. Loại vô nghĩa.

** Bạn có thể trả về dưới dạng đối tượng (yêu cầu sự phản chiếu để truy cập thuộc tính của nó - yeech) hoặc bạn có thể "bỏ qua ví dụ". đã biết loại của đối tượng sẽ trông như thế nào, vậy tại sao không chỉ tạo một đối tượng và điền vào nó ngay từ đầu?

4

Tôi đã viết một phương thức tương đối ngắn sẽ phân tích cú pháp JSON và trả về tên/giá trị Từ điển có thể được truy cập tương tự như đối tượng thực tế trong JavaScript.

Dưới đây là một cách sử dụng mẫu của các phương pháp dưới đây:

var obj = ParseJsonToDictionary("{FirstName: \"Chris\", \"Address\":{Street:\"My Street\",Number:123}}"); 

// Access the Address.Number value 
object streetNumber = ((Dictionary<string, object>)obj["Address"])["Number"]; 

Và, đây là mã cho phương pháp ParseJsonToDictionary:

public static Dictionary<string, object> ParseJsonToDictionary(string json) 
{ 
    var d = new Dictionary<string, object>(); 

    if (json.StartsWith("{")) 
    { 
     json = json.Remove(0, 1); 
     if (json.EndsWith("}")) 
      json = json.Substring(0, json.Length - 1); 
    } 
    json.Trim(); 

    // Parse out Object Properties from JSON 
    while (json.Length > 0) 
    { 
     var beginProp = json.Substring(0, json.IndexOf(':')); 
     json = json.Substring(beginProp.Length); 

     var indexOfComma = json.IndexOf(','); 
     string endProp; 
     if (indexOfComma > -1) 
     { 
      endProp = json.Substring(0, indexOfComma); 
      json = json.Substring(endProp.Length); 
     } 
     else 
     { 
      endProp = json; 
      json = string.Empty; 
     } 

     var curlyIndex = endProp.IndexOf('{'); 
     if (curlyIndex > -1) 
     { 
      var curlyCount = 1; 
      while (endProp.Substring(curlyIndex + 1).IndexOf("{") > -1) 
      { 
       curlyCount++; 
       curlyIndex = endProp.Substring(curlyIndex + 1).IndexOf("{"); 
      } 
      while (curlyCount > 0) 
      { 
       endProp += json.Substring(0, json.IndexOf('}') + 1); 
       json = json.Remove(0, json.IndexOf('}') + 1); 
       curlyCount--; 
      } 
     } 

     json = json.Trim(); 
     if (json.StartsWith(",")) 
      json = json.Remove(0, 1); 
     json.Trim(); 


     // Individual Property (Name/Value Pair) Is Isolated 
     var s = (beginProp + endProp).Trim(); 


     // Now parse the name/value pair out and put into Dictionary 
     var name = s.Substring(0, s.IndexOf(":")).Trim(); 
     var value = s.Substring(name.Length + 1).Trim(); 

     if (name.StartsWith("\"") && name.EndsWith("\"")) 
     { 
      name = name.Substring(1, name.Length - 2); 
     } 

     double valueNumberCheck; 
     if (value.StartsWith("\"") && value.StartsWith("\"")) 
     { 
      // String Value 
      d.Add(name, value.Substring(1, value.Length - 2)); 
     } 
     else if (value.StartsWith("{") && value.EndsWith("}")) 
     { 
      // JSON Value 
      d.Add(name, ParseJsonToDictionary(value)); 
     } 
     else if (double.TryParse(value, out valueNumberCheck)) 
     { 
      // Numeric Value 
      d.Add(name, valueNumberCheck); 
     } 
     else 
      d.Add(name, value); 
    } 

    return d; 
} 

Tôi biết phương pháp này có thể là một chút thô, và nó có thể có thể được tối ưu hóa khá một chút, nhưng đó là bản nháp đầu tiên và nó chỉ hoạt động.

Ngoài ra, trước khi bạn khiếu nại về nó không sử dụng cụm từ thông dụng, hãy nhớ rằng không phải ai cũng hiểu biểu thức thông thường và viết theo cách đó sẽ gây khó khăn hơn cho người khác để khắc phục nếu cần. Ngoài ra, tôi hiện không biết biểu thức chính quy quá rõ ràng và việc phân tích cú pháp chuỗi dễ dàng hơn.

+0

@Cảm ơn Chris vì một đoạn mã đẹp để phân tích chuỗi Json –

Các vấn đề liên quan