Fly*_*wat 39 wcf serialization json
当我使用DataContractJsonSerializer序列化枚举值时,它序列化枚举的数值,而不是字符串名称.
IE:
enum foo
{
bar,
baz
}
Run Code Online (Sandbox Code Playgroud)
序列化foo.bar的值将返回"0",而不是"bar".
相反,我更喜欢它,有没有办法覆盖它?
编辑:
因为我不想更改序列化程序,所以我使用了一个简单的解决方法.
我在类中公开了一个属性来序列化,调用ToString值,即:
// Old
[DataMember]
public EnumType Foo
{
get { return _foo; }
set { _foo = value; }
}
// New, I still kept the EnumType but I only serialize the string version
public EnumType Foo
{
get { return _foo; }
set { _foo = value; }
}
[DataMember]
public string FooType
{
get { return _foo.ToString(); }
private set {}
}
Run Code Online (Sandbox Code Playgroud)
Dar*_*rov 25
看起来这是设计的,这种行为无法改变:
枚举成员值在JSON中被视为数字,这与在数据协定中处理它们的方式不同,它们作为成员名称包含在内.
这是一个使用替代(以及更好和更可扩展的IMO)序列化器的示例,它可以实现您的目标:
using System;
using Newtonsoft.Json;
class Program
{
static void Main(string[] args)
{
var baz = Foo.Baz;
var serializer = new JsonSerializer();
serializer.Converters.Add(new JsonEnumTypeConverter());
serializer.Serialize(Console.Out, baz);
Console.WriteLine();
}
}
enum Foo
{
Bar,
Baz
}
public class JsonEnumTypeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Foo);
}
public override void WriteJson(JsonWriter writer, object value)
{
writer.WriteValue(((Foo)value).ToString());
}
public override object ReadJson(JsonReader reader, Type objectType)
{
return Enum.Parse(typeof(Foo), reader.Value.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
Jas*_*rts 10
为了得到2路串行/ deserilization WCF的JSON你可以添加一个字符串类型的第二获取设置属性,当你在建设你的javascript JSON对象使用字符串命名属性,在服务器端使用强类型枚举的版本:如
public class DTOSearchCriteria
{
public int? ManufacturerID { get; set; }
public int? ModelID { get; set; }
private SortBy _sort;
public SortBy SortType
{
get
{
return _sort;
}
set
{
_sort = value;
}
}
public String Sort
{
get
{
return _sort.ToString();
}
set
{
_sort = (SortBy) Enum.Parse(typeof(SortBy), value);
}
}
public int PageSize { get; set; }
public int PageNumber { get; set; }
}
public enum SortBy
{
PriceDescending,
PriceAscending
}
Run Code Online (Sandbox Code Playgroud)
小智 10
我疯狂地试图找到这个问题的优雅解决方案,因为似乎每个人都默认使用Newtonsoft的序列化程序来解决这个问题.尽管Newtonsoft提供了更多功能,但它确实存在一些严重缺陷.要列举几个:为参数构造函数,疯狂行为的需要,如果你想序列化实现IEnumerable的类,它执行时使用抽象类型非常糟糕(因为它不利用KnownTypes属性,和解决方法生成将您的内部命名空间公开给调用者的详细输出.
另一方面,在MVC4 WebApi解决方案上使用DataContractJsonSerializer时,几乎没有关于如何自定义DataContractJsonSerializer的示例.
我花了一段时间才找到一个表示枚举为字符串的解决方案,并解决了DataContractJsonSerializer附带的已知DateTime格式问题.
第一部分 - 将这些扩展方法放在扩展类中~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
#region JSon
/// <summary>Serializes an object to JSon.</summary>
/// <param name="obj">The object to serialize.</param>
/// <returns>Returns a byte array with the serialized object.</returns>
/// <remarks>This implementation outputs dates in the correct format and enums as string.</remarks>
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed.")]
public static byte[] SerializeJson(this object obj)
{
using (MemoryStream b = new MemoryStream())
{
SerializeJson(obj, b);
return b.ToArray();
}
}
/// <summary>Serializes an object to JSon.</summary>
/// <param name="obj">The object to serialize.</param>
/// <param name="stream">The stream to write to.</param>
/// <remarks>This implementation outputs dates in the correct format and enums as string.</remarks>
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed.")]
public static void SerializeJson(this object obj, Stream stream)
{
var settings = new DataContractJsonSerializerSettings();
settings.DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat("yyyy-MM-dd'T'HH:mm:ssZ");
settings.DataContractSurrogate = new EnumToStringDataContractSurrogate();
var type = obj == null ? typeof(object) : obj.GetType();
var enumerationValue = obj as System.Collections.IEnumerable;
var fixedValue = enumerationValue != null
? type.IsGenericType && !type.GetGenericArguments()[0].IsInterface
? enumerationValue.ToArray(type.GetGenericArguments()[0])
: enumerationValue.OfType<object>().ToArray()
: obj;
if (enumerationValue != null && (!type.IsGenericType || (type.IsGenericType || type.GetGenericArguments()[0].IsInterface)))
{
var firstMember = (fixedValue as System.Collections.IEnumerable).OfType<object>().FirstOrDefault();
if (firstMember != null)
fixedValue = enumerationValue.ToArray(firstMember.GetType());
}
var fixedType = obj == null
? type
: fixedValue.GetType();
var jsonSer = new DataContractJsonSerializer(fixedType, settings);
jsonSer.WriteObject(stream, fixedValue);
}
/// <summary>
/// Deserializes an object.
/// </summary>
/// <typeparam name="T">The output type of the object.</typeparam>
/// <param name="data">The serialized contents.</param>
/// <returns>Returns the typed deserialized object.</returns>
/// <remarks>This implementation outputs dates in the correct format and enums as string.</remarks>
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "JSon")]
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed.")]
public static T DeserializeJSon<T>(this byte[] data)
{
using (MemoryStream b = new MemoryStream(data))
return DeserializeJSon<T>(b);
}
/// <summary>Deserializes a JSon object.</summary>
/// <typeparam name="T">The output type of the object.</typeparam>
/// <param name="stream">The stream to read from.</param>
/// <returns>Returns the typed object.</returns>
/// <remarks>This implementation outputs dates in the correct format and enums as string.</remarks>
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "JSon")]
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed.")]
public static T DeserializeJSon<T>(this Stream stream)
{
var settings = new DataContractJsonSerializerSettings();
settings.DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat("yyyy-MM-dd'T'HH:mm:ssZ");
settings.DataContractSurrogate = new EnumToStringDataContractSurrogate();
var jsonSer = new DataContractJsonSerializer(typeof(T), settings);
return (T)jsonSer.ReadObject(stream);
}
/// <summary>Deserializes a JSon object.</summary>
/// <param name="data">The serialized contents.</param>
/// <param name="targetType">The target type.</param>
/// <returns>Returns the typed deserialized object.</returns>
/// <remarks>This implementation outputs dates in the correct format and enums as string.</remarks>
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "JSon")]
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed.")]
public static object DeserializeJSon(this byte[] data, Type targetType)
{
using (MemoryStream b = new MemoryStream(data))
{
return DeserializeJSon(b, targetType);
}
}
/// <summary>Deserializes a JSon object.</summary>
/// <param name="data">The serialized contents.</param>
/// <param name="targetType">The target type.</param>
/// <returns>Returns the typed deserialized object.</returns>
/// <remarks>This implementation outputs dates in the correct format and enums as string.</remarks>
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "JSon")]
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "Reviewed.")]
public static object DeserializeJSon(this Stream data, Type targetType)
{
var settings = new DataContractJsonSerializerSettings();
settings.DateTimeFormat = new System.Runtime.Serialization.DateTimeFormat("yyyy-MM-dd'T'HH:mm:ssZ");
settings.DataContractSurrogate = new EnumToStringDataContractSurrogate();
var jsonSer = new DataContractJsonSerializer(targetType, settings);
return jsonSer.ReadObject(data);
}
/// <summary>Enumerator contract surrogate.</summary>
internal class EnumToStringDataContractSurrogate : IDataContractSurrogate
{
Type IDataContractSurrogate.GetDataContractType(Type type)
{
return type == typeof(Enum) ? typeof(string) : type;
}
object IDataContractSurrogate.GetDeserializedObject(object obj, Type targetType)
{
if (targetType.IsEnum)
{
return obj == null
? System.Enum.GetValues(targetType).OfType<int>().FirstOrDefault()
: System.Enum.Parse(targetType, obj.ToString());
}
return obj;
}
object IDataContractSurrogate.GetObjectToSerialize(object obj, Type targetType)
{
if (obj is Enum)
{
var pair = Enum.GetName(obj.GetType(), obj);
return pair;
}
return obj;
}
object IDataContractSurrogate.GetCustomDataToExport(Type clrType, Type dataContractType)
{
throw new NotImplementedException();
}
object IDataContractSurrogate.GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
throw new NotImplementedException();
}
void IDataContractSurrogate.GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
{
throw new NotImplementedException();
}
Type IDataContractSurrogate.GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
throw new NotImplementedException();
}
System.CodeDom.CodeTypeDeclaration IDataContractSurrogate.ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
throw new NotImplementedException();
}
}
#endregion
/// <summary>Creates an array from a non generic source.</summary>
/// <param name="source">The source.</param>
/// <param name="type">The target type of the array.</param>
/// <returns>Returns a typed array.</returns>
public static Array ToArray(this IEnumerable source, Type type)
{
var param = Expression.Parameter(typeof(IEnumerable), "source");
var cast = Expression.Call(typeof(Enumerable), "Cast", new[] { type }, param);
var toArray = Expression.Call(typeof(Enumerable), "ToArray", new[] { type }, cast);
var lambda = Expression.Lambda<Func<IEnumerable, Array>>(toArray, param).Compile();
return lambda(source);
}
Run Code Online (Sandbox Code Playgroud)
第二部分 - 通过封装DataContractJsonSerializer创建自己的格式化~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// <summary>Custom implementation of DataContract formatter.</summary>
public class DataContractJsonFormatter : MediaTypeFormatter
{
/// <summary>Creates a new instance.</summary>
public DataContractJsonFormatter()
{
SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
}
/// <summary>Gets if the formatter the write a given type.</summary>
/// <param name="type">The type to handle.</param>
/// <returns>Returns if the formatter the write a given type.</returns>
public override bool CanWriteType(Type type)
{
return true;
}
/// <summary>Gets if the formatter the read a given type.</summary>
/// <param name="type">The type to handle.</param>
/// <returns>Returns if the formatter the read a given type.</returns>
public override bool CanReadType(Type type)
{
return true;
}
/// <summary>Deserializes an object.</summary>
/// <param name="type">The target type.</param>
/// <param name="readStream">The stream to read from.</param>
/// <param name="content">The http content.</param>
/// <param name="formatterLogger">A logger.</param>
/// <returns>Returns the deserialized object.</returns>
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger)
{
var task = Task<object>.Factory.StartNew(() =>
{
return readStream.DeserializeJSon(type);
});
return task;
}
/// <summary>Serializes an object.</summary>
/// <param name="type">The target type.</param>
/// <param name="value">The object to serialize.</param>
/// <param name="writeStream">The stream to write to.</param>
/// <param name="content">The http content.</param>
/// <param name="transportContext">The context.</param>
/// <returns>Returns the deserialized object.</returns>
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
{
var task = Task.Factory.StartNew(() =>
{
value.SerializeJson(writeStream);
});
return task;
}
}
Run Code Online (Sandbox Code Playgroud)
第三部分 - 编辑你的Global.asax文件并使用你的新JSon格式化程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// <summary>Event handlers of when the application starts.</summary>
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
protected void Application_Start()
{
//Register my custom DataContract JSon serializer
GlobalConfiguration.Configuration.Formatters.Insert(0, new DataContractJsonFormatter());
//Register areas
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
// BundleConfig.RegisterBundles(BundleTable.Bundles);
//JSON serialization config
var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.UseDataContractJsonSerializer = false;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17579 次 |
| 最近记录: |