我正在使用Json.Net Nuget包将Json对象反序列化为C#具体对象。我的Json对象具有snake_casing" property_name"但我的C#对象是关注camelCasing" propertyName"。当我反序列化对象时,它正常工作,但是当我尝试从WCF服务反序列化相同的Json对象时,它没有映射到C#类的属性。
var eventMessage = JsonConvert.DeserializeObject<TestClass>( JsonMessage );
ServiceContract:
[ServiceContract]
public interface IService
{
[OperationContract]
[FaultContract( typeof( MessageUnAuthenticatedFault ))]
[WebInvoke( Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Process" )]
string Process( string message );
}
这是我的DataContract
[DataContract]
public class TestClass
{
[DataMember]
public long Id { get; set; }
[DataMember]
[JsonProperty( PropertyName = "request_name" )]
public string RequestedName { get; set; }
[DataMember]
[JsonProperty( PropertyName = "request_type" )]
public string RequestType { get; set; }
[DataMember]
[JsonProperty( PropertyName = "request_key" )]
public string RequestKey { get; set; }
[DataMember]
[JsonProperty( PropertyName = "descriptive_name" )]
public string DescriptiveName { get; set; } = null;
[DataMember]
[JsonProperty( PropertyName = "owner_internal_id" )]
public string OwnerInternalId { get; set; }
[DataMember]
public string URL { get; set; }
[DataMember]
public Status Status { get; set; }
[DataMember]
public DateTime? Created { get; set; }
[DataMember]
public DateTime? Modified { get; set; }
}
Json对象看起来像这样:
{"generated": "2016-08-04T08:06+0000", "request_type": "test", "request_key": "1111", "descriptive_name": "Description", "owner_internal_id": "1213456", "Created":"2016-08-04T08:00"}
为什么Json.Net在WCF服务的情况下没有正确映射属性?
P.S:我的服务仅支持JSON请求和响应。
此致
答案 0 :(得分:2)
<强>更新强>
现在你已经在问题中包含了服务合同,我发现存在一个更基本的问题。 WCF用于交换Data Contract objects,并且在XML和JSON之间是格式无关的。它是如此不可知,以至于没有直接的方式来访问底层的原始请求或响应流。相反,WCF坚持为您进行绑定。由于您上传的JSON不是JSON原语,因此尝试将其绑定到string message
会失败。
相反,您需要按照
的方式定义服务[ServiceContract]
public interface IService
{
[OperationContract]
[FaultContract( typeof( MessageUnAuthenticatedFault ))]
[WebInvoke( Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Process" )]
ResponseClass Process( TestClass message );
}
ResponseClass
是你想要归还的地方。请查看WCF rest service to get post JSON data and retrieve JSON data with DataContract示例。
如果您确实需要基础帖子流进行手动解析,那么可能会尝试WCF REST Service JSON Post data和WCF + REST: Where is the request data?中的技巧。
原始答案
WCF不使用Json.NET进行JSON序列化。它使用DataContractJsonSerializer
。因此,使用[JsonProperty]
注释您的类型将不起作用。相反,您需要设置DataMemberAttribute.Name
,即:
[DataContract]
public class TestClass
{
[DataMember]
public long Id { get; set; }
[DataMember(Name = "request_name")]
public string RequestedName { get; set; }
[DataMember(Name = "request_type")]
public string RequestType { get; set; }
[DataMember(Name = "request_key")]
public string RequestKey { get; set; }
[DataMember(Name = "descriptive_name")]
public string DescriptiveName { get; set; }
[DataMember(Name = "owner_internal_id")]
public string OwnerInternalId { get; set; }
[DataMember]
public string URL { get; set; }
[DataMember]
public Status Status { get; set; }
[DataMember]
public DateTime? Created { get; set; }
[DataMember]
public DateTime? Modified { get; set; }
}
要使用此序列化程序测试独立JSON反序列化,您可以使用以下帮助程序方法:
public static partial class DataContractJsonSerializerHelper
{
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
public static string SerializeJson<T>(T obj, DataContractJsonSerializer serializer = null)
{
serializer = serializer ?? new DataContractJsonSerializer(obj.GetType());
using (var memory = new MemoryStream())
{
serializer.WriteObject(memory, obj);
memory.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(memory))
{
return reader.ReadToEnd();
}
}
}
public static T DeserializeJson<T>(string json, DataContractJsonSerializer serializer = null)
{
serializer = serializer ?? new DataContractJsonSerializer(typeof(T));
using (var stream = GenerateStreamFromString(json))
{
var obj = serializer.ReadObject(stream);
return (T)obj;
}
}
}
然后做:
var test = DataContractJsonSerializerHelper.DeserializeJson<TestClass>(jsonString);
您还必须使用Microsoft的首选DateTime
格式设置"/Date(1329159196126-0500)/"
属性格式,或使用代理进行反序列化以进行手动解析。有关详细信息,请参阅DataContractJsonSerializer - Deserializing DateTime within List和WCF Extensibility – Serialization Surrogates;有关背景信息,请参阅ASP.NET AJAX: Inside JSON date and time string。或者只为每个DateTime
使用代理属性,例如:
[IgnoreDataMember]
public DateTime? Created { get; set; }
[DataMember(Name = "Created")]
string CreatedString
{
get
{
if (Created == null)
return null;
// From https://stackoverflow.com/questions/114983/given-a-datetime-object-how-do-i-get-a-iso-8601-date-in-string-format
return Created.Value.ToString("s", System.Globalization.CultureInfo.InvariantCulture);
}
set
{
if (string.IsNullOrEmpty(value))
Created = null;
else
Created = DateTime.Parse(value);
}
}
[DataMember]
public DateTime? Modified { get; set; }
}
如果您真的想将Json.NET与WCF一起用于反序列化,则需要做一些工作。请参阅C# WCF REST - How do you use JSON.Net serializer instead of the default DataContractSerializer?,可能还有Using Custom WCF Body Deserialization without changing URI Template Deserialization。
有关各种Microsoft框架使用的JSON序列化程序的详细信息,请参阅Json serializers in ASP.NET and other。