2014-11-22 308 views
1

我有一個類用於表示一個標識,它包含一個字符串的值。Newtonsoft.Json DeserializeObject爲guid傳遞null值00000000-0000-0000-0000-000000000000

然後我有另一個類用於表示一個事件,這包括一個標識對象和一個字符串名稱。

我可以從對象到JSON字符串精細序列化,我得到的字符串:

{"Id":{"Value":"2e4146c2-66c9-4637-8936-29ccfc5df638"},"Name":"Jon Doe"}

然而,當我從上面的JSON去反對,在MyIdentity構造函數的字符串identityValue在爲傳遞"00000000-0000-0000-0000-000000000000"

我也曾嘗試爲MyIdentity提供兩個構造函數,一個用於字符串,另一個用於Guid,但結果相同。這背後的想法是將數據存儲爲字符串,但要記住,如果需要,我們可以將其轉換爲Guid(因爲身份將由字符串或Guid形成)。

public class MyEntityId : MyIdentity 
{ 
    public MyEntityId(Guid identityValue) 
     : base(identityValue) 
    { 
    } 
} 

public abstract class MyIdentity 
{ 
    protected readonly bool convertableAsGuid; 
    protected readonly string value; 

    public string Value { get { return this.value; } } 

    public MyIdentity(string identityValue) 
    { 
     this.value = identityValue; 

     Guid guid; 
     if(Guid.TryParse(identityValue, out guid)==false) 
      this.convertableAsGuid = false; 
    } 

    public MyIdentity(Guid identityValue) 
    { 
     this.value = identityValue.ToString(); 
     this.convertableAsGuid = true; 
    } 
} 

static void Main(string[] args) 
{ 
    var evnt = new MyEvent(new MyEntityId(Guid.NewGuid()), "Jon Doe"); 

    var eventHeaders = new Dictionary<string, object> 
    { 
     {"EventClrTypeName", evnt.GetType().AssemblyQualifiedName} 
    }; 
    var serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None }; 
    var metadata = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventHeaders, serializerSettings)); 
    var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(evnt, serializerSettings)); 
    string dataAsString = Encoding.UTF8.GetString(data); 

    var eventClrTypeName = JObject.Parse(Encoding.UTF8.GetString(metadata)).Property("EventClrTypeName").Value; 
    var obj = JsonConvert.DeserializeObject(dataAsString, Type.GetType((string)eventClrTypeName)); 
    // stepping through the above, a zero initialised GUID string is passed in to MyIdentity constructor 
} 

由於@hvd慷慨評論,這似乎是唯一的價值有一個獲得的財產,如果我添加了一組屬性還那麼它的工作原理(所以我相信沒有實際使用的構造函數的字符串值) 。我不想讓身份認同的原因是編程設計,它是一種身份,一旦創建就不應該改變。

我可以住在一個公共獲取和受保護的財產集,我已經嘗試過關鍵字[JsonProperty],它的工作原理...但是我不想用這些屬性來裝飾我的域對象 - 有沒有另一種方式?

+2

的問題也許在於'Value'屬性沒有setter和不能映射到構造函數參數,但這並不能幫助您修復它。 – hvd 2014-11-22 15:15:02

回答

1

如果我理解正確,您在初始化反序列化的Guid時遇到問題,並且您不想創建setter或使用屬性進行成功的反序列化。請注意,我通過移除接受Guid參數的構造函數來更改MyIdentity類,因爲它不是必需的,因爲它不會正確初始化convertableAsGuid屬性並創建類,因爲您沒有將它發佈到您的項目上,所以更改Guid邏輯的解析題。我還創建了在反序列化過程中使用的MyCustomConverter類。下面是類:

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var jObject = JObject.Load(reader); 
     existingValue = new MyEvent(new MyEntityId(jObject["Id"]["Value"].ToString()), jObject["Name"].ToString()); 

     return existingValue; 
    } 

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

public class MyEvent 
{ 
    public MyEntityId Id { get; set; } 

    public string Name { get; set; } 

    public MyEvent(MyEntityId id, string name) 
    { 
     Id = id; 
     Name = name; 
    } 
} 

public class MyEntityId : MyIdentity 
{ 
    public MyEntityId(string identityValue) 
     : base(identityValue) 
    { 
    } 
} 

public abstract class MyIdentity 
{ 
    protected readonly bool convertableAsGuid; 
    protected readonly string value; 

    public string Value { get { return this.value; } } 

    public MyIdentity(string identityValue) 
    { 
     this.value = identityValue; 

     Guid guid; 
     if (Guid.TryParse(identityValue, out guid)) 
      this.convertableAsGuid = true; 
    } 
} 

,這裏是序列化和反序列化邏輯:

static void Main(string[] args) 
{ 
    var evnt = new MyEvent(new MyEntityId(Guid.NewGuid().ToString()), "Jon Doe"); 

    var eventHeaders = new Dictionary<string, object> 
     { 
      {"EventClrTypeName", evnt.GetType().AssemblyQualifiedName} 
     }; 
    var serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None }; 
    var metadata = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventHeaders, serializerSettings)); 
    var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(evnt, serializerSettings)); 
    string dataAsString = Encoding.UTF8.GetString(data); 

    var eventClrTypeName = JObject.Parse(Encoding.UTF8.GetString(metadata)).Property("EventClrTypeName").Value; 
    var obj = JsonConvert.DeserializeObject<MyEvent>(dataAsString, new JsonConverter[] {new MyCustomConverter()}); 
} 

演示:https://dotnetfiddle.net/asRtEI