2014-06-27 51 views
3

我有一個類,即trues到SER \ DES的對象,給它,使用Json.net反序列化類具有2個非默認的構造函數

public class JsonSerializer 
{ 
    public string Serialize(object toSerialaze) 
    { 
     return JsonConvert.SerializeObject(toSerialaze); 
    } 

    public T Deserialize<T>(string toDeserialaze) 
    { 
     return JsonConvert.DeserializeObject<T>(toDeserialaze); 
    } 
} 

,並給予它anobject這樣一類

public class Isbn 
    { 
     private readonly int _groupCode; 
     private readonly int _publisherCode; 
     private readonly int _titleCode; 
     private readonly int _checkCode; 
     private static readonly Regex Regex = new Regex(@"^\s*\d*\s*-\s*\d*\s*-\s*\d*\s*-\s*\d*\s*$"); 

     public Isbn(int groupCode, int publisherCode, int titleCode, int checkCode) 
     { 
      _groupCode = groupCode; 
      _publisherCode = publisherCode; 
      _titleCode = titleCode; 
      _checkCode = checkCode; 
     } 

     public Isbn(string isbn) 
     { 
      if (isbn == null) 
       throw new ArgumentNullException("isbn"); 
      if (isbn == "") return; 
      if (!IsValid(isbn)) return; 
      var isbnStrings = isbn.Split(new[] {'-', ' '}, StringSplitOptions.RemoveEmptyEntries); 
      _groupCode = Convert.ToInt32(isbnStrings[0]); 
      _publisherCode = Convert.ToInt32(isbnStrings[1]); 
      _titleCode = Convert.ToInt32(isbnStrings[2]); 
      _checkCode = Convert.ToInt32(isbnStrings[3]); 
     } 
    } 

我收到一個異常: 附加信息:無法找到用於類型Library.Isbn的構造函數。一個類應該有一個默認構造函數,一個帶參數的構造函數或一個帶有JsonConstructor屬性標記的構造函數。 我知道,我可能把[JsonConstructor]放在構造函數之前,我需要在反序列化時使用,但我不想讓Isbn類知道Json。 我該怎麼做另一種方式呢?我該如何讓JsonConverter知道使用哪個構造函數?

+0

樣品jsons? .. –

回答

2

我想這個答案是有點晚了,但有人可能會想使用它。

您可以通過創建自定義做JsonConverter

public class IsbnConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(Isbn); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.StartObject) 
     { 
      var dict = new Dictionary<string, int>(); 
      serializer.Populate(reader, dict); 
      return new Isbn(dict["groupCode"], dict["publisherCode"], dict["titleCode"], dict["checkCode"]); 
     } 

     if (reader.TokenType == JsonToken.String) 
     { 
      return new Isbn((string)reader.Value); 
     } 

     return null; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

你唯一需要的就是這種轉換器傳遞給JsonConvert.DeserializeObject

var yourobj = JsonConvert.DeserializeObject<T>(json, new IsbnConverter()); 

現在deserializetion可以同時爲JSON的

工作
{ .... , isbn:{groupCode:1,publisherCode:2,titleCode:3,checkCode:4}, ...... } 
{ .... , isbn:"1-2-3-4", .... } 

對於ex;

public class Book 
{ 
    public string Title { get; set; } 
    public Isbn isbn { get; set; } 
} 

string json1 = @"{Title:""Title 1"", isbn:{groupCode:1,publisherCode:2,titleCode:3,checkCode:4}}"; 
string json2 = @"{Title:""Title 2"", isbn:""1-2-3-4""}"; 

var book1 = JsonConvert.DeserializeObject<Book>(json1, new IsbnConverter()); 
var book2 = JsonConvert.DeserializeObject<Book>(json2, new IsbnConverter()); 
+0

「我認爲這個答案有點晚了」呃?詢問後大約一個小時? – weston

0

一種選擇是爲了序列化而擁有一個不同的類。然後映射到您的原件,無論是手動或使用AutoMapper。

作爲獎勵,您會發現您的業務對象可以自由重構,無需擔心序列化會發生什麼。因爲你是對的,所以不應該知道json。

用靜態方法

另一種選擇是降低構造的號碼,我儘量不要有一個以上的,往往有沒有(我指的是沒有公共構造)更換公共構造。

例子:

public Isbn(int groupCode, int publisherCode, int titleCode, int checkCode) 
    { 
     _groupCode = groupCode; 
     _publisherCode = publisherCode; 
     _titleCode = titleCode; 
     _checkCode = checkCode; 
    } 

    public static Isbn FromString(string isbn) 
    { 
     if (isbn == null) 
      throw new ArgumentNullException("isbn"); 
     if (isbn == "") return; 
     if (!IsValid(isbn)) return; 
     var isbnStrings = isbn.Split(new[] {'-', ' '}, StringSplitOptions.RemoveEmptyEntries); 
     var groupCode = Convert.ToInt32(isbnStrings[0]); 
     var publisherCode = Convert.ToInt32(isbnStrings[1]); 
     var titleCode = Convert.ToInt32(isbnStrings[2]); 
     var checkCode = Convert.ToInt32(isbnStrings[3]); 
     return new Isbn(groupCode, publisherCode, titleCode, checkCode); 
    } 
+0

weston,謝謝你的回答!這是一個非常好的主意,不要超過1個cjnstructor! –

+0

不客氣,即使您想接受其他答案,也可以點擊向上箭頭爲答案投票。 – weston

+0

如果你喜歡這個檢查http://stackoverflow.com/questions/194496/static-constructors-vs-instance-normal-constructors關於這種方法的更多參數,它基本上來自一本書Effective Java,其中大部分適用同樣對C# – weston

相關問題