我有一些具有以下结构的课程
public class A {
[JsonProperty(PropertyName = "prop_b")]
public B PropB {get; set;}
}
public class B {
[JsonProperty(PropertyName = "val1")]
public int Val1 {get; set;}
[JsonProperty(PropertyName = "val2")]
public int Val2 {get; set;}
}
将序列化为以下方案的JSON:
{
"prop_b": { "val1": X, "val2": Y }
}
有没有办法让我跳过B
并直接序列化字段,而不改变类结构?我认为会有一些属性,或者我可以实现一个属性。
{
"val1": X,
"val2": Y
}
答案 0 :(得分:2)
一种可能是创建一个JsonConverter。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
public sealed class ImportChildAttribute : Attribute
{
}
class ImportChildJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
var attr = CustomAttributeExtensions.GetCustomAttribute(objectType.GetTypeInfo(), typeof(ImportChildAttribute), true);
if (attr != null)
{
var props = objectType.GetProperties();
if (props.Length != 1)
throw new NotSupportedException($"Only supports {nameof(ImportChildAttribute)} on classes with one property.");
return true;
}
return false;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Deserialize the object into the first property.
var props = objectType.GetProperties();
var obj = Activator.CreateInstance(objectType);
var val = serializer.Deserialize(reader, props[0].PropertyType);
props[0].SetValue(obj, val);
return obj;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// Find the only property and serialize it.
var props = value.GetType().GetProperties();
serializer.Serialize(writer, props[0].GetValue(value));
}
}
然后,您可以将ImportChild
属性放在您想要具有此行为的所有类上。
[ImportChild]
public class A
{
[JsonProperty(PropertyName = "prop_b")]
public B PropB { get; set; }
}
public class B
{
[JsonProperty(PropertyName = "val1")]
public int Val1 { get; set; }
[JsonProperty(PropertyName = "val2")]
public int Val2 { get; set; }
}
最后,尝试一下:
var settings = new JsonSerializerSettings
{
Converters = new[] { new ImportChildJsonConverter() },
Formatting = Formatting.Indented
};
var obj = new A { PropB = new B { Val1 = 1, Val2 = 2 } };
string json = JsonConvert.SerializeObject(obj, settings);
Console.WriteLine(json);
/* Outputs:
{
"val1": 1,
"val2": 2
}
*/
var originalObj = JsonConvert.DeserializeObject<A>(json, settings);
// originalObj and obj are now identical.