使用套件: Json.NET 7.0.1 : https://www.nuget.org/packages/Newtonsoft.Json/7.0.1 AutoMapper 4.04 : https://www.nuget.org/packages/AutoMapper/4.0.4
今天碰到一個問題,就是有個API回傳值的欄位是不固定無法掌握的,所以只好在轉型成強型別時以object當做該屬性的類別,但JsonConvert碰到類別為Object的東西就會轉成JObject ,而AutoMapper對應JObject會炸掉。以下是簡單時間的範例Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 void Main ( ) { Mapper.CreateMap<source, destination>() .ForMember(d => d.d_name, o => o.MapFrom(s => s.name)) .ForMember(d => d.d_obj, o => o.MapFrom(s => s.obj)); source test = new source { name = "test" , obj = new {code = 100 }, }; var result = Mapper.Map<destination>(test); result.Dump(); } public class source { public string name { get ; set ; } public object obj { get ; set ; } } public class destination { public string d_name { get ; set ; } public object d_obj { get ; set ; } }
Source與Destination都有個property為object的類別屬性,在Main()裡面也想好兩個類別的對應關係,並且先準備好Source 然後透過AutoMapper轉出Result,在以上的範例執行正確沒問題
換個寫法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 void Main ( ) { Mapper.CreateMap<source, destination>() .ForMember(d => d.d_name, o => o.MapFrom(s => s.name)) .ForMember(d => d.d_obj, o => o.MapFrom(s => s.obj)); source test = JsonConvert.DeserializeObject<source>("{\"name\":\"test\",\"obj\" : {\"code\":100}}" ); var result = Mapper.Map<destination>(test); result.Dump(); } public class source { public string name { get ; set ; } public object obj { get ; set ; } } public class destination { public string d_name { get ; set ; } public object d_obj { get ; set ; } }
差別只在於原本Source改成透過Json.Net由字串轉回來而已,這時候只要執行到AutoMapper那一行就會爆炸,錯誤訊息如下
AutoMapperMappingException:
Mapping types: JObject -> JObject Newtonsoft.Json.Linq.JObject -> Newtonsoft.Json.Linq.JObject
Destination path: destination.d_obj.d_obj
Source value: { “code”: 100 }
JsonConvert碰到目標為Object型別的欄位,會轉成JObject塞進去,AutoMapper用它來對應, 所以如果要解決這個問題需要做一些處理
1 2 3 4 5 6 7 8 9 10 11 12 13 Mapper.CreateMap<source, destination>() .ForMember(d => d.d_name, o => o.MapFrom(s => s.name)) .ForMember(d => d.d_obj, o => o.ResolveUsing(s => { if (s.obj is JObject) { var temp = s.obj as JObject; return temp.ToObject<Dictionary<string , object >>(); } return s.obj; }));
這樣就可以正確地取出了