2 回答

TA貢獻1848條經驗 獲得超2個贊
您可以以編程方式將 aJsonConverter應用于模型類中的一個或多個屬性,而無需通過 custom 使用屬性ContractResolver。這是一個簡單的示例,它將您應用于您班級AllCapsConverter中的LastName財產。Person(如果您正在尋找更強大的解決方案,請查看@dbc 的答案。我的目的是展示可能可行的最簡單示例。)
public class CustomResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty prop = base.CreateProperty(member, memberSerialization);
if (prop.DeclaringType == typeof(Person) && prop.UnderlyingName == "LastName")
{
prop.Converter = new AllCapsConverter();
}
return prop;
}
}
這是更新的測試和Person模型,顯示了如何使用解析器:
public class PersonSerializationTest
{
[Fact]
public void SerializePerson_LastNameCaps()
{
var person = new Person
{
FirstName = "George",
LastName = "Washington"
};
var settings = new JsonSerializerSettings
{
ContractResolver = new CustomResolver()
};
var serialized = JsonConvert.SerializeObject(person, settings);
var expected = @"{""FirstName"":""George"",""LastName"":""WASHINGTON""}";
Assert.Equal(expected, serialized);
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}

TA貢獻1752條經驗 獲得超4個贊
您可以使用從IContractResolverDefaultContractResolver.
首先,ConfigurableContractResolver從這個答案中獲取如何添加元數據來描述 JSON.Net 中哪些屬性是日期:
public class ConfigurableContractResolver : DefaultContractResolver
{
// This contract resolver taken from the answer to
// https://stackoverflow.com/questions/46047308/how-to-add-metadata-to-describe-which-properties-are-dates-in-json-net
// https://stackoverflow.com/a/46083201/3744182
readonly object contractCreatedPadlock = new object();
event EventHandler<ContractCreatedEventArgs> contractCreated;
int contractCount = 0;
void OnContractCreated(JsonContract contract, Type objectType)
{
EventHandler<ContractCreatedEventArgs> created;
lock (contractCreatedPadlock)
{
contractCount++;
created = contractCreated;
}
if (created != null)
{
created(this, new ContractCreatedEventArgs(contract, objectType));
}
}
public event EventHandler<ContractCreatedEventArgs> ContractCreated
{
add
{
lock (contractCreatedPadlock)
{
if (contractCount > 0)
{
throw new InvalidOperationException("ContractCreated events cannot be added after the first contract is generated.");
}
contractCreated += value;
}
}
remove
{
lock (contractCreatedPadlock)
{
if (contractCount > 0)
{
throw new InvalidOperationException("ContractCreated events cannot be removed after the first contract is generated.");
}
contractCreated -= value;
}
}
}
protected override JsonContract CreateContract(Type objectType)
{
var contract = base.CreateContract(objectType);
OnContractCreated(contract, objectType);
return contract;
}
}
public class ContractCreatedEventArgs : EventArgs
{
public JsonContract Contract { get; private set; }
public Type ObjectType { get; private set; }
public ContractCreatedEventArgs(JsonContract contract, Type objectType)
{
this.Contract = contract;
this.ObjectType = objectType;
}
}
public static class ConfigurableContractResolverExtensions
{
public static ConfigurableContractResolver Configure(this ConfigurableContractResolver resolver, EventHandler<ContractCreatedEventArgs> handler)
{
if (resolver == null || handler == null)
throw new ArgumentNullException();
resolver.ContractCreated += handler;
return resolver;
}
}
然后,創建一個方法來配置JsonObjectContractfor Person,如下所示:
public static class JsonContractExtensions
{
public static void ConfigurePerson(this JsonContract contract)
{
if (!typeof(Person).IsAssignableFrom(contract.UnderlyingType))
return;
var objectContract = contract as JsonObjectContract;
if (objectContract == null)
return;
var property = objectContract.Properties.Where(p => p.UnderlyingName == nameof(Person.LastName)).Single();
property.Converter = new AllCapsConverter();
}
}
最后序列化如下:
// Cache the contract resolver statically for best performance.
var resolver = new ConfigurableContractResolver()
.Configure((s, e) => { e.Contract.ConfigurePerson(); });
var settigs = new JsonSerializerSettings
{
ContractResolver = resolver,
};
var person = new Person
{
FirstName = "George",
LastName = "Washington"
};
var serialized = JsonConvert.SerializeObject(person, settigs);
筆記:
ConfigurableContractResolver與其創建它,不如對那里的必要邏輯進行子類化DefaultContractResolver、覆蓋DefaultContractResolver.CreateProperty和硬編碼Person.LastName。然而,創建一個允許在運行時組合定制的可配置解析器似乎更有用且可重用。
用它來寫你的大寫字符串AllCapsConverter.WriteJson()會更簡單:writer.WriteValue(string)
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var upper = ((string)value).ToUpperInvariant();
writer.WriteValue(upper);
}
您可能希望緩存合約解析器以獲得最佳性能。
- 2 回答
- 0 關注
- 187 瀏覽
添加回答
舉報