使用Json.Net,我的对象中的属性需要特别小心才能序列化/反序列化它们.作为后代JsonConverter
,我成功地完成了这一任务.这是执行此操作的常用方法:
public class SomeConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
...
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
...
}
public override bool CanConvert(Type objectType)
{
...
}
}
class SomeClass
{
[JsonProperty, JsonConverter(typeof(SomeConverter))]
public SomeType SomeProperty;
}
//Later on, in code somewhere
SomeClass SomeObject = new SomeClass();
string json = JsonConvert.SerializeObject(SomeObject, new SomeConverter());
Run Code Online (Sandbox Code Playgroud)
我的代码问题是我需要在每个序列化/反序列化中引入我的自定义转换器.在我的项目中,有很多情况我不能这样做.例如,我正在使用其他利用Json.Net的外部项目,他们将在我的SomeClass
实例上工作.但由于我不想或无法改变他们的代码,我无法介绍我的转换器.
有没有什么方法可以static
在Json.Net中使用某个成员注册我的转换器,所以无论序列化/反序列化发生在哪里,我的转换器总是存在?
我有一个通用类型,它包装一个原始类型以赋予它值相等语义
public class ValueObject<T>
{
public T Value { get; }
public ValueObject(T value) => Value = value;
// various other equality members etc...
}
Run Code Online (Sandbox Code Playgroud)
它的用法如下:
public class CustomerId : ValueObject<Guid>
{
public CustomerId(Guid value) : base(value) { }
}
public class EmailAddress : ValueObject<string>
{
public EmailAddress(string value) : base(value) { }
}
Run Code Online (Sandbox Code Playgroud)
问题是在序列化类型时,例如:
public class Customer
{
public CustomerId Id { get; }
public EmailAddress Email { get; }
public Customer(CustomerId id, EmailAddress email)
{
Id = id; …
Run Code Online (Sandbox Code Playgroud) 在我的代码中,我有一些对象(和方法)可以使用许多仅是简单Integer的ID。当我在各处设置值时,为了从编译器中获得一些帮助,我将这些简单的int转换为类型更强的对象(类型别名)。像这样:
public struct CustomId
{
private readonly int id;
public CustomId(int id) => this.id = id;
public static implicit operator int(CustomId cid) => cid.id;
public static implicit operator CustomId(int id) => new CustomId(id);
}
Run Code Online (Sandbox Code Playgroud)
但是因为它实际上只是一个具有更特定名称的int,所以我真的想将它序列化为int,例如在JSON中,Person看起来像这样:
{
"Name": "ASD",
"Id": 42 // this would be the serialized result of my CustomId
}
Run Code Online (Sandbox Code Playgroud)
虽然在这种情况下我设法构建了一个自定义JsonConverter,并且如果我使用Newtonsoft JSON可以正常工作,但我想知道是否有更好的方法,属性或接口来实现(系统中的某些功能)。 Runtime.Serialization命名空间),大多数序列化程序框架都将考虑在内,因此我不必为JSON,XML,Protobuf等序列化编写自定义转换器,而只需依赖一些通用解决方案即可。
我有一个类Foo
,其FooConverter
定义如下:
[JsonConverter(typeof(FooConverter))]
public class Foo
{
public string Something { get; set; }
}
public class FooConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((Foo)value).Something);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var str = reader.ReadAsString();
if (str == null)
{
throw new JsonSerializationException();
}
// return new Foo {Something = serializer.Deserialize<string>(reader)};
return new Foo {Something = str};
}
public override bool CanConvert(Type objectType) …
Run Code Online (Sandbox Code Playgroud) 我有一个名为 InstrumentConfigValues 的类,其属性具有实现接口的类型。现在我有一个名为 InstrumentConfig 的枚举,它具有一组值。这些值就像 json 文件中的键。我想映射类似[JsonProperty(InstrumentConfig.LowDiskpace.ToString()]
.
出于某种原因,它不允许这样做并抱怨说:
属性参数必须是常量表达式
我特别提到了许多帖子JsonStringEnumConverter。但是如何使用枚举键映射每个属性。我也看到了这篇文章JsonSerializationSettings但无法与我的问题相关联。请帮忙/
public class InstrumentConfigValues : IInstrumentConfig
{
public double SpaceNeededForSingleRun
{
get; set;
}
public int NumberOfInputSlots
{
get; set;
}
public int SupportedChannelCount
{
get; set;
}
}
//I want this inheritance as some other class wants to access the values.
public abstract class InstrumentConfigReadWrite : InstrumentConfigValues
{
protected ReturnCodes PopulateValuesFromJObject(JObject jObject, string path)
{
try
{
if (JsonConvert.DeserializeObject<InstrumentConfigValues>(jObject.ToString()) == null)
{
return ReturnCodes.ErrorReadingFile; …
Run Code Online (Sandbox Code Playgroud)