我有很多来自mssql数据库的linq2sql商务模型。表之间存在一些关联,这很好。整个模型是单独组装的。我正在使用JSON.NET库进行序列化。
现在我需要将这些模型序列化为JSON并告诉它使用哪些属性以及现在使用哪些属性。使用if属性是不可能的,但我也不喜欢元数据类的想法。
所以我一直在考虑以这种方式使用扩展方法:
public static class User {
public static object GetSerializable(this DataModel.User user) {
return new {
user.Id, user.LoginName, user.FirstName, user.LastName
}
}
}
这很好,但我不知道如何在这样的情况下使用它:
[JsonObject]
public class AuthModel {
[JsonProperty]
public DataModel.User { get; set; }
}
您是否知道如何有效地使用这些扩展方法?还是其他一些完全不同的想法?
答案 0 :(得分:0)
您可以使用Fluent Json将它们转换为json。此配置可以在不使用属性的情况下在代码中完成。
选项2:您可以使用Custom Serializer
选项3:您可以使用KeyValuePairConverter。将持久化类转换为字典并使用它。
答案 1 :(得分:0)
好吧我决定采用基于自定义JsonConverter的方法,结果与上面的方法非常相似。它看起来像这样:
public abstract class SerializeSelectorConverter<TModel> : JsonConverter where TModel: class
{
protected abstract object GetSerializableObject( TModel model );
public override bool CanWrite { get { return true; } }
public override bool CanConvert(Type objectType)
{
return objectType == typeof(TModel);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, GetSerializableObject( value as TModel ));
}
public override bool CanRead { get { return false; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后我就做了一个类:
[JsonObject]
public class AuthModel {
[JsonProperty]
[JsonConverter(typeof(UserConverter))]
public DataModel.User { get; set; }
}
private class UserConverter : SerializeSelectorConverter<DataModel.User>
{
protected override object GetSerializableObject(DataModel.User model)
{
return new
{
model.Id,
model.LoginName,
model.FirstName,
model.LastName
};
}
}
没有一些复杂的配置或元数据类就足够简单。所有内容都经过编译器的正确验证,因此在发生更改时不会出现拼写错误和问题。
答案 2 :(得分:0)
我编写了一个自定义JsonConverter来处理这种情况,因为源类有一个枚举需要序列化的接口。
您的类加序列化界面:
public interface IUser {
Guid Id { get; set; }
string LoginName { get; set; }
...
}
public class User : IUser {
...implementation...
}
转换器:
public class InterfaceExtractorJsonConverter<T> : JsonConverter {
private class InterfaceDictionary<T> : Dictionary<string, object> { }
private PropertyInfo[] InterfaceProperties {
get { return typeof(T).GetProperties(); }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
var dictionary = new InterfaceDictionary<T>();
foreach (var property in InterfaceProperties) {
dictionary[property.Name] = value.GetType().GetProperty(property.Name).GetValue(value, null);
}
serializer.Serialize(writer, dictionary);
}
private object ReadNestedObject(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
while (reader.TokenType == JsonToken.Comment) {
if (!reader.Read())
throw new Exception("Unexpected end.");
}
switch (reader.TokenType) {
case JsonToken.StartObject:
case JsonToken.StartArray:
return serializer.Deserialize(reader, objectType);
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.String:
case JsonToken.Boolean:
case JsonToken.Null:
case JsonToken.Undefined:
case JsonToken.Date:
case JsonToken.Bytes:
return reader.Value;
default:
throw new Exception(string.Format("Unexpected token when converting object: {0}", reader.TokenType));
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var obj = Activator.CreateInstance(objectType);
while (reader.Read()) {
switch (reader.TokenType) {
case JsonToken.PropertyName:
string propertyName = reader.Value.ToString();
if (!reader.Read())
throw new Exception("Unexpected end.");
if (!InterfaceProperties.Any(p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase))) {
reader.Skip();
continue;
}
var property = objectType.GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var innerObj = ReadNestedObject(reader, property.PropertyType, existingValue, serializer);
property.SetValue(obj, innerObj, null);
break;
case JsonToken.Comment:
break;
case JsonToken.EndObject:
return obj;
}
}
throw new Exception("Unexpected end.");
}
public override bool CanConvert(Type objectType) {
return objectType.GetInterfaces().Contains(typeof(T));
}
}
可以对转换器进行大量优化......