[英]Deserializing JSON, nested object properties to be in parent object. C#
I have following JSON that I'm writing object model to deserialize into:我有以下 JSON,我正在编写对象模型以反序列化:
{
"company_webhooks": [
{
"company_webhook": {
"id": 42,
"url": "https://keeptruckin.com/callbacktest/842b02",
"secret": "fe8b75de0a4e5898f0011faeb8c93654",
"format": "json",
"actions": [
"vehicle_location_received",
"vehicle_location_updated"
],
"enabled": false
}
},
{
"company_webhook": {
"id": 43,
"url": "https://keeptruckin.com/callbacktest/a6a783",
"secret": "66a7368063cb21887f546c7af91be59c",
"format": "json",
"actions": [
"vehicle_location_received",
"vehicle_location_updated"
],
"enabled": false
}
},
{
"company_webhook": {
"id": 44,
"url": "https://keeptruckin.com/callbacktest/53a52c",
"secret": "4451dc96513b3a67107466dd2c4d9589",
"format": "json",
"actions": [
"vehicle_location_received",
"vehicle_location_updated"
],
"enabled": false
}
},
{
"company_webhook": {
"id": 45,
"url": "https://keeptruckin.com/callbacktest/6fb337",
"secret": "4177fbd88c30faaee03a4362648bd663",
"format": "json",
"actions": [
"vehicle_location_received",
"vehicle_location_updated"
],
"enabled": false
}
},
{
"company_webhook": {
"id": 46,
"url": "https://keeptruckin.com/callbacktest/8cd6da",
"secret": "6e41817a048b009435e5102fca17db55",
"format": "json",
"actions": [
"vehicle_location_received",
"vehicle_location_updated"
],
"enabled": false
}
}
],
"pagination": {
"per_page": 25,
"page_no": 1,
"total": 5
}
}
Here is what I have:这是我所拥有的:
[DataContract]
public class KeepTruckinResponse
{
[DataMember(Name = "company_webhooks", EmitDefaultValue = false)]
public KeepTruckinCompanyWebHook[] WebHooks { get; set; }
[DataMember(Name = "pagination", EmitDefaultValue = false)]
public KeepTruckinPagination Pagination { get; set; }
public string RawJSON { get; set; }
}
[DataContract]
public class KeepTruckinPagination
{
[DataMember(Name = "per_page", EmitDefaultValue = false)]
public int PerPage { get; set; }
[DataMember(Name = "page_no", EmitDefaultValue = false)]
public int PageNumber { get; set; }
[DataMember(Name = "total", EmitDefaultValue = false)]
public int Total { get; set; }
}
[DataContract(Name = "company_webhook")]
public class KeepTruckinCompanyWebHook
{
[DataMember(Name = "id", EmitDefaultValue = false)]
public int Id { get; set; }
[DataMember(Name = "url", EmitDefaultValue = false)]
public string Url { get; set; }
}
Obviously, when I deserialize JSON I don't get KeepTruckinCompanyWebHook
properties because the way they send collection is "nested".显然,当我反序列化 JSON 时,我没有得到
KeepTruckinCompanyWebHook
属性,因为它们发送集合的方式是“嵌套的”。 I almost have to create another object inside KeepTruckinCompanyWebHook
with properties.我几乎必须在
KeepTruckinCompanyWebHook
创建另一个具有属性的对象。 But I'd like to keep my object model as it is.但我想保持我的对象模型原样。 Is it possible with .NET serializer?
.NET 序列化程序可以吗?
We use DataContractJsonSerializer
like so:我们像这样使用
DataContractJsonSerializer
:
var ser = new DataContractJsonSerializer(typeof(KeepTruckinResponse));
response = ser.ReadObject(ms) as KeepTruckinResponse;
At this point we don't want to use NewtonSoft.Json此时我们不想使用 NewtonSoft.Json
Yes, this is possible, but you will need some custom code to do it.是的,这是可能的,但您需要一些自定义代码才能做到这一点。
It's a little ugly, but you can create a custom IDataContractSurrogate
class to deserialize each JSON object inside the company_webhooks
array into a Dictionary<string, Dictionary<string, object>>
, and then copy the values from the nested dictionary structure into an instance of your KeepTruckinCompanyWebHook
class.有点难看,但是您可以创建一个自定义的
IDataContractSurrogate
类,将company_webhooks
数组中的每个 JSON 对象反序列化为Dictionary<string, Dictionary<string, object>>
,然后将嵌套字典结构中的值复制到你的KeepTruckinCompanyWebHook
类。 Here's the code you would need for the surrogate:这是代理所需的代码:
class MyDataContractSurrogate : IDataContractSurrogate
{
public Type GetDataContractType(Type type)
{
if (type == typeof(KeepTruckinCompanyWebHook))
{
return typeof(Dictionary<string, Dictionary<string, object>>);
}
return type;
}
public object GetDeserializedObject(object obj, Type targetType)
{
if (obj.GetType() == typeof(Dictionary<string, Dictionary<string, object>>) &&
targetType == typeof(KeepTruckinCompanyWebHook))
{
var webHook = new KeepTruckinCompanyWebHook();
var outerDict = (Dictionary<string, Dictionary<string, object>>)obj;
var innerDict = outerDict["company_webhook"];
foreach (PropertyInfo prop in GetDataMemberProperties(typeof(KeepTruckinCompanyWebHook)))
{
DataMemberAttribute att = prop.GetCustomAttribute<DataMemberAttribute>();
object value;
if (innerDict.TryGetValue(att.Name, out value))
{
prop.SetValue(webHook, value);
}
}
return webHook;
}
return obj;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
if (obj.GetType() == typeof(KeepTruckinCompanyWebHook) &&
targetType == typeof(Dictionary<string, Dictionary<string, object>>))
{
var webHook = (KeepTruckinCompanyWebHook)obj;
var outerDict = new Dictionary<string, Dictionary<string, object>>();
var innerDict = new Dictionary<string, object>();
outerDict.Add("company_webhook", innerDict);
foreach (PropertyInfo prop in GetDataMemberProperties(typeof(KeepTruckinCompanyWebHook)))
{
DataMemberAttribute att = prop.GetCustomAttribute<DataMemberAttribute>();
innerDict.Add(att.Name, prop.GetValue(webHook));
}
return outerDict;
}
return obj;
}
private IEnumerable<PropertyInfo> GetDataMemberProperties(Type type)
{
return type.GetProperties().Where(p => p.CanRead && p.CanWrite && p.GetCustomAttribute<DataMemberAttribute>() != null);
}
// ------- The rest of these methods do not need to be implemented -------
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
throw new NotImplementedException();
}
public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
{
throw new NotImplementedException();
}
public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
{
throw new NotImplementedException();
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
throw new NotImplementedException();
}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
throw new NotImplementedException();
}
}
To use the surrogate, you'll need to create an instance of DataContractJsonSerializerSettings
and pass it to the DataContractJsonSerializer
with the following properties set.要使用代理,您需要创建
DataContractJsonSerializerSettings
的实例并将其传递给DataContractJsonSerializer
并设置以下属性。 Note that since we require the UseSimpleDictionaryFormat
setting, this solution will only work with .Net 4.5 or later.请注意,由于我们需要
UseSimpleDictionaryFormat
设置,因此此解决方案仅适用于 .Net 4.5 或更高版本。
var settings = new DataContractJsonSerializerSettings();
settings.DataContractSurrogate = new MyDataContractSurrogate();
settings.KnownTypes = new List<Type> { typeof(Dictionary<string, Dictionary<string, object>>) };
settings.UseSimpleDictionaryFormat = true;
Here is a demo:这是一个演示:
public class Program
{
public static void Main(string[] args)
{
string json = @"
{
""company_webhooks"": [
{
""company_webhook"": {
""id"": 42,
""url"": ""https://keeptruckin.com/callbacktest/842b02"",
""secret"": ""fe8b75de0a4e5898f0011faeb8c93654"",
""format"": ""json"",
""actions"": [
""vehicle_location_received"",
""vehicle_location_updated""
],
""enabled"": false
}
},
{
""company_webhook"": {
""id"": 43,
""url"": ""https://keeptruckin.com/callbacktest/a6a783"",
""secret"": ""66a7368063cb21887f546c7af91be59c"",
""format"": ""json"",
""actions"": [
""vehicle_location_received"",
""vehicle_location_updated""
],
""enabled"": false
}
},
{
""company_webhook"": {
""id"": 44,
""url"": ""https://keeptruckin.com/callbacktest/53a52c"",
""secret"": ""4451dc96513b3a67107466dd2c4d9589"",
""format"": ""json"",
""actions"": [
""vehicle_location_received"",
""vehicle_location_updated""
],
""enabled"": false
}
},
{
""company_webhook"": {
""id"": 45,
""url"": ""https://keeptruckin.com/callbacktest/6fb337"",
""secret"": ""4177fbd88c30faaee03a4362648bd663"",
""format"": ""json"",
""actions"": [
""vehicle_location_received"",
""vehicle_location_updated""
],
""enabled"": false
}
},
{
""company_webhook"": {
""id"": 46,
""url"": ""https://keeptruckin.com/callbacktest/8cd6da"",
""secret"": ""6e41817a048b009435e5102fca17db55"",
""format"": ""json"",
""actions"": [
""vehicle_location_received"",
""vehicle_location_updated""
],
""enabled"": false
}
}
],
""pagination"": {
""per_page"": 25,
""page_no"": 1,
""total"": 5
}
}";
var settings = new DataContractJsonSerializerSettings();
settings.DataContractSurrogate = new MyDataContractSurrogate();
settings.KnownTypes = new List<Type> { typeof(Dictionary<string, Dictionary<string, object>>) };
settings.UseSimpleDictionaryFormat = true;
KeepTruckinResponse response = Deserialize<KeepTruckinResponse>(json, settings);
foreach (KeepTruckinCompanyWebHook wh in response.WebHooks)
{
Console.WriteLine("Id: " + wh.Id + ", Url: " + wh.Url);
}
}
public static T Deserialize<T>(string json, DataContractJsonSerializerSettings settings)
{
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
var ser = new DataContractJsonSerializer(typeof(T), settings);
return (T)ser.ReadObject(ms);
}
}
public static string Serialize(object obj, DataContractJsonSerializerSettings settings)
{
using (MemoryStream ms = new MemoryStream())
{
var ser = new DataContractJsonSerializer(obj.GetType(), settings);
ser.WriteObject(ms, obj);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
}
[DataContract]
public class KeepTruckinResponse
{
[DataMember(Name = "company_webhooks", EmitDefaultValue = false)]
public KeepTruckinCompanyWebHook[] WebHooks { get; set; }
[DataMember(Name = "pagination", EmitDefaultValue = false)]
public KeepTruckinPagination Pagination { get; set; }
public string RawJSON { get; set; }
}
[DataContract]
public class KeepTruckinPagination
{
[DataMember(Name = "per_page", EmitDefaultValue = false)]
public int PerPage { get; set; }
[DataMember(Name = "page_no", EmitDefaultValue = false)]
public int PageNumber { get; set; }
[DataMember(Name = "total", EmitDefaultValue = false)]
public int Total { get; set; }
}
[DataContract(Name = "company_webhook")]
public class KeepTruckinCompanyWebHook
{
[DataMember(Name = "id", EmitDefaultValue = false)]
public int Id { get; set; }
[DataMember(Name = "url", EmitDefaultValue = false)]
public string Url { get; set; }
}
Output:输出:
Id: 42, Url: https://keeptruckin.com/callbacktest/842b02
Id: 43, Url: https://keeptruckin.com/callbacktest/a6a783
Id: 44, Url: https://keeptruckin.com/callbacktest/53a52c
Id: 45, Url: https://keeptruckin.com/callbacktest/6fb337
Id: 46, Url: https://keeptruckin.com/callbacktest/8cd6da
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.