2009-07-24 36 views
9

Tôi có một cấu trúc trong C# bao bọc một guid. Tôi đang sử dụng DataContractJsonSerializer để tuần tự hóa một đối tượng có chứa một thể hiện của lớp đó. Khi tôi đang sử dụng một guid trực tiếp, nó đã được tuần tự hóa thành một chuỗi đơn giản, nhưng bây giờ nó được tuần tự hóa thành một cặp tên/giá trị. Dưới đây là một bài kiểm tra NUnit và mã hỗ trợ đó chứng tỏ vấn đề:Làm thế nào tôi có thể làm cho DataContractJsonSerializer tuần tự hóa một đối tượng dưới dạng chuỗi?

private static string ToJson<T>(T data) 
    { 
     DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof (T)); 

     using (MemoryStream ms = new MemoryStream()) 
     { 
      serializer.WriteObject(ms, data); 
      return Encoding.Default.GetString(ms.ToArray()); 
     } 
    } 

    [Serializable] 
    private class ID 
    { 
     private Guid _value; 

     public static explicit operator ID(Guid id) 
     { 
      return new ID { _value = id }; 
     } 

     public static explicit operator Guid(ID id) 
     { 
      return id._value; 
     } 
    } 

    [Test] 
    public void IDShouldSerializeLikeGuid() 
    { 
     Guid guid = Guid.NewGuid(); 
     ID id = (ID) guid; 
     Assert.That(ToJson(id), Is.EqualTo(ToJson(guid))); 
    } 

Và bài kiểm tra đầu ra Á hậu:

NUnit.Framework.AssertionException: Expected string length 38 but was 49. Strings differ at index 0. 
    Expected: ""7511fb9f-3515-4e95-9a04-06580753527d"" 
    But was: "{"_value":"7511fb9f-3515-4e95-9a04-06580753527d"}" 
    -----------^ 

Làm thế nào để serialize struct của tôi như là một chuỗi đồng bằng và thực hiện thử nghiệm của tôi vượt qua?

Trả lời

10

Trong trường hợp này có vẻ như bạn không thực sự muốn JSON, bạn muốn có một biểu diễn chuỗi. Trong trường hợp đó tôi sẽ tạo ra một giao diện như thế này:

interface IStringSerialized 
{ 
    String GetString(); 
} 

Thực hiện giao diện này vào loại ID của bạn (và tất cả các loại khác mà có những yêu cầu tương tự).

[Serializable] 
class ID : IStringSerialized 
{ 
    private Guid _value; 

    public static explicit operator ID(Guid id) 
    { 
     return new ID { _value = id }; 
    } 

    public static explicit operator Guid(ID id) 
    { 
     return id._value; 
    } 

    public string GetString() 
    { 
     return this._value.ToString(); 
    } 
} 

Sau đó, thay đổi phương pháp tuần tự của bạn để xử lý những trường hợp đặc biệt:

private static string ToJson<T>(T data) 
{ 
    IStringSerialized s = data as IStringSerialized; 

    if (s != null) 
     return s.GetString(); 

    DataContractJsonSerializer serializer 
       = new DataContractJsonSerializer(typeof(T)); 

    using (MemoryStream ms = new MemoryStream()) 
    { 
     serializer.WriteObject(ms, data); 
     return Encoding.Default.GetString(ms.ToArray()); 
    } 
} 
+0

Tôi bỏ qua một số phức tạp để làm cho vấn đề rõ ràng, nhưng trong ứng dụng thực sự này là trong bối cảnh của một đối tượng có chứa một danh sách trong đó. Tôi muốn mã thực sự sản xuất ["guid1", "guid2"], không phải [{"_value": "guid1"}, {"_value": "guid2"}]. Thật không may, cách tiếp cận đó sẽ không hiệu quả đối với tôi. Cảm ơn cho ý tưởng mặc dù! –

+7

Không sử dụng Mã hóa mặc định vì nó sẽ làm hỏng mọi ký tự không phải ANSI. Tôi hiện đang xử lý các tin nhắn push trên điện thoại di động. Mã của bạn sẽ có thể xử lý các ngôn ngữ khác. Thay vào đó, sử dụng UTF8. trả về Mã hóa.UTF8.GetString (ms.ToArray()); – midspace

0

Hãy thử sử dụng JavaScriptSerializer Lớp nó sẽ ngăn chặn các vấn đề sưng lên chìa khóa, giá trị.

+1

nhưng sau đó bạn sẽ mất tất cả các dữ liệu hợp đồng thuộc tính mà bạn có trong bạn đối tượng bạn muốn serialize (như emitdefaultvalue) – silver

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