2009-06-03 40 views
49

Tôi cần phải deserialize một số đối tượng JavaScript được trình bày trong JSON thành một lớp C# thích hợp. Với các tính năng tốt đẹp của các thuộc tính tự động, tôi muốn có chúng trong các lớp này thay vì chỉ có các trường. Thật không may, công cụ tuần tự hóa .NET (ít nhất, theo mặc định) hoàn toàn bỏ qua các thuộc tính tự động trên deserialization và chỉ quan tâm đến trường sao lưu, mà rõ ràng là không có trong đối tượng JavaScript.C# tự động hóa thuộc tính tự động hóa của JSON

Cho rằng có no standard way to name backing fields và thành thật mà nói, tôi thậm chí không muốn bận tâm với phương pháp "chúng ta hãy tạo đối tượng JavaScript trông giống như có phương pháp C# sao lưu" vì nó có vẻ hơi bẩn, cách duy nhất tôi có thể tuần tự hóa các trường JavaScript thành các thuộc tính tự động của C# nếu tôi có thể ép buộc công cụ tuần tự hóa bằng cách nào đó bỏ qua trường sao lưu và sử dụng thuộc tính trực tiếp. Thật không may, tôi không thể tìm ra cách này được thực hiện hoặc nếu điều này có thể được thực hiện ở tất cả. Có những câu chuyện mới trên trang chủ.

EDIT: Dưới đây là một ví dụ:

Javascript:

function Cat() 
{ 
    this.Name = "Whiskers"; 
    this.Breed = "Tabby"; 
} 
var cat = new Cat(); 

Đây là sau đó tuần tự để "{Name: 'Whiskers'}".

C class #:

[Serializable()] 
public class Cat 
{ 
    public string Name { get; set; } 
    public string Breed { get; set; } 
} 

Và mã deserialization, thất bại:

new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream); 

Và nó là rõ ràng từ các ngoại lệ mà nó không thành công bởi vì nó đang tìm kiếm các lĩnh vực sao lưu.

EDIT2: Đây là ngoại lệ, nếu điều đó giúp (không có ngoại lệ bên trong):

System.Runtime.Serialization.SerializationException

"Các loại hợp đồng dữ liệu 'Test.Cat' không thể được deserialized vì thành viên dữ liệu bắt buộc '<Name>k__BackingField, <Breed>k__BackingField' không phải là được tìm thấy. "

+0

Bạn có thể đăng một ví dụ về ý của mình không? –

+0

@John Saunders - giả sử tôi có một đối tượng JavaScript được gọi là "Mèo" với một trường duy nhất có tên "Tên" với giá trị "Râu". Giả sử điều này được biểu diễn bằng JSON. Tôi muốn lấy JSON này và tuần tự hóa nó thành một thể hiện của lớp C# Cat (được viết bởi tôi) để quá trình tuần tự hóa điền vào thuộc tính tự động "Tên" của cá thể với "Râu". –

+0

... nhưng vấn đề là bộ nối tiếp đang tìm kiếm trường sao lưu (ví dụ: " k_backingField" nhưng không nhất thiết với tên này ") và không phải là" Tên ". –

Trả lời

79

Điều đang xảy ra ở đây là trình gỡ rối đang cố đoán tên của trường sao lưu của bạn. Bạn có thể giải quyết điều này bằng cách thêm ánh xạ rõ ràng (DataContract/DataMember thuộc tính) như thế này:

[DataContract] 
public class Cat 
{ 
    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public string Breed { get; set; } 
} 
+0

+1 Câu hỏi đầu tiên tôi trả lời, nhưng tôi không có đại diện để trả lời câu trả lời này vào thời điểm đó! – amelvin

+2

Tôi muốn +2 nếu có thể. Tìm kiếm câu trả lời cho điều này một chút ngay bây giờ. – Kelly

+0

siêu! Tôi đã bỏ thuộc tính [DataContract] :( – Ruutert

20

Bạn có thể làm điều này với JavaScriptSerializer tìm thấy trong không gian tên System.Web.Script.Serialization:

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
Cat c = serializer.Deserialize<Cat>(jsonString); 

Tôi có POCO đối tượng có đặc tính tự động và điều này làm việc tốt.

EDIT: Tôi đã viết về JSON Serializers in .NET so sánh bộ nối tiếp này với DataContractJsonSerializer.

+0

Vâng có vẻ như tôi sẽ bị mắc kẹt với tốt cũ JsonExSerializer http://code.google.com/p/ jsonexserializer/ –

1

Tôi giả sử bạn đang chuyển dữ liệu qua dịch vụ web. Nếu bạn đang sử dụng lớp WebService với thuộc tính ScriptMethod không được giải quyết, các phương thức dịch vụ web có thể đọc JSON nguyên bản. Họ thậm chí sử dụng cùng một JavaScriptSerializer đã được đề cập ở trên. Nếu bạn đang sử dụng WCF tôi là một chút mờ hơn trên logic.

Nhưng hãy đảm bảo đối tượng JSON của bạn đang trả về dữ liệu cho MỌI thuộc tính trong lớp học của bạn. Trong lỗi của bạn, có đề cập đến một tài sản giống mà không có trong ví dụ của bạn.

Ngoài ra, ở phía JavaScript, làm với tính chất động của JavaScript, thật dễ dàng để thêm các thuộc tính mới vào đối tượng của bạn. Điều này đôi khi có thể dẫn đến tham chiếu vòng tròn. Bạn nên xóa bất kỳ dữ liệu bổ sung nào mà bạn có thể đã thêm (giống như bạn đang gửi dữ liệu qua phương thức web, sau đó thêm lại sau khi bạn đã hoàn tất).

+0

Không, thật không may đó không phải là dịch vụ web.Đó là một yêu cầu ajax đơn giản chuyển dữ liệu trong json tới máy chủ. Tôi khá chắc chắn rằng không có tài liệu tham khảo vòng tròn. Bạn nói đúng rằng trong ví dụ không có tài sản giống nhưng trong mã thực sự của tôi, tất cả các thuộc tính đều có. Cảm ơn các đề xuất mặc dù :) –

+0

Về phía JavaScript của sự vật: làm cách nào bạn chuyển đổi đối tượng JavaScript sang JSON? –

+0

@Chris Brandsma: Cách thông thường, với json2.js: http://www.json.org/json2.js –

5

baretta's answer giải quyết được k__BackingField sưng lên cho tôi. Chỉ cần một phụ lục nhỏ mà bạn có thể trang trí lớp học này để tự động serialize vào hoặc XML hoặc JSON trong một cách tương tự:

[Serializable, XmlRoot, DataContract] 
public class Cat 
{ 
    [XmlElement] 
    [DataMember] 
    public string Name { get; set; } 
    [XmlElement] 
    [DataMember] 
    public string Breed { get; set; } 
} 

... và sau đó sử dụng một DataContractJsonSerializer hoặc XmlSerializer để chuẩn bị cho thiết bị đầu cuối của bạn.

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