将.Net对象序列化为json,使用xml属性进行控制

我有一个.Net对象,我已经将其序列化为Xml并使用Xml属性进行修饰。 我现在想将相同的对象序列化为Json,最好使用Newtonsoft Json.Net库。

我想直接从内存中的.Net对象转到Json字符串(不先串行化为Xml)。 我不希望向类中添加任何Json属性,而是希望Json序列化程序使用现有的Xml属性。

public class world{ [XmlIgnore] public int ignoreMe{ get; } [XmlElement("foo")] public int bar{ get; } [XmlElement("marco")] public int polo{ get; } } 

 { "foo":0, "marco":0 } 

使用[JsonProperty(PropertyName="foo")]属性并设置PropertyName

事实certificate这不是Newtonsoft Json.Net库的现有function。 我写了一个补丁并将其上传到Json.Net问题跟踪器 ( 此处存档链接):

这允许以下内容:

  • XmlIgnore就像JsonIgnore一样工作。
  • XmlElementAttribute.ElementName将更改Json属性名称。
  • XmlType.AnonymousType将禁止将对象打印到Json(XmlContractResolver.SuppressAnonymousType属性改变了这种行为) 这有点像hacky,因为我必须像以前一样学习Json.Net的内部结构。

您可以创建一个自定义合约解析程序,它允许您对属性进行调整,并将它们设置为忽略XmlIgnoreAttribute的设置位置。

 public class CustomContractResolver : DefaultContractResolver { private readonly JsonMediaTypeFormatter formatter; public CustomContractResolver(JsonMediaTypeFormatter formatter) { this.formatter = formatter; } public JsonMediaTypeFormatter Formatter { [DebuggerStepThrough] get { return this.formatter; } } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); this.ConfigureProperty(member, property); return property; } private void ConfigureProperty(MemberInfo member, JsonProperty property) { if (Attribute.IsDefined(member, typeof(XmlIgnoreAttribute), true)) { property.Ignored = true; } } } 

通过在序列化对象时设置JsonSerializerSettings的ContractResolver属性,可以使用应用此自定义解析程序

https://www.newtonsoft.com/json/help/html/ContractResolver.htm

 string json = JsonConvert.SerializeObject( product, // this is your object that has xml attributes on it that you want ignored Formatting.Indented, new JsonSerializerSettings { ContractResolver = new CustomResolver() } ); 

如果您正在使用WebApi,则可以将其全局设置为适用于所有合同。

 var config = GlobalConfiguration.Configuration; var jsonSettings = config.Formatters.JsonFormatter.SerializerSettings; jsonSettings.ContractResolver = new CustomContractResolver(); 

下面的类可用于将对象树的部分序列化(和反序列化)为XML,然后再序列化为JSON。

用法

 [JsonObject] public class ClassToSerializeWithJson { [JsonProperty] public TypeThatIsJsonSerializable PropertySerializedWithJsonSerializer {get; set; } [JsonProperty] [JsonConverter(typeof(JsonXmlConverter))] public TypeThatIsXmlSerializable PropertySerializedWithCustomSerializer {get; set; } } 

JsonXmlConverter类

 public class JsonXmlConverter : JsonConverter where TType : class { private static readonly XmlSerializer xmlSerializer = new XmlSerializer(typeof(TType)); public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var xml = ToXml(value as TType); using (var stream = new StringReader(xml)) { var xDoc = XDocument.Load(stream); var json = JsonConvert.SerializeXNode(xDoc); writer.WriteRawValue(json); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { // consume the 'null' token to set the reader in the correct state JToken.Load(reader); return null; } var jObj = JObject.Load(reader); var json = jObj.ToString(); var xDoc = JsonConvert.DeserializeXNode(json); var xml = xDoc.ToString(); return FromXml(xml); } public override bool CanRead => true; public override bool CanConvert(Type objectType) => objectType == typeof(TType); private static TType FromXml(string xmlString) { using (StringReader reader = new StringReader(xmlString)) return (TType)xmlSerializer.Deserialize(reader); } private static string ToXml(TType obj) { using (StringWriter writer = new StringWriter()) using (XmlWriter xmlWriter = XmlWriter.Create(writer)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add(String.Empty, String.Empty); xmlSerializer.Serialize(xmlWriter, obj, ns); return writer.ToString(); } } }