Serializar el objeto .Net a json, controlado mediante atributos xml

Tengo un objeto .Net que he estado serializando a Xml y está decorado con atributos Xml. Ahora quisiera serializar el mismo objeto a Json, preferiblemente utilizando la biblioteca Newtonsoft Json.Net .

Me gustaría pasar directamente del objeto .Net en memoria a una cadena Json (sin primero serializar a Xml). No deseo agregar ningún atributo de Json a la clase, sino que me gustaría que el serializador Json use los atributos de XML existentes.

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

se convierte en

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

Use el [JsonProperty(PropertyName="foo")] y establezca el PropertyName .

Resulta que esta no era una característica existente de la biblioteca Newtonsoft Json.Net. Escribí un parche y lo subí al rastreador de problemas de Json.Net (enlace archivado aquí ):

Esto permite lo siguiente:

  • XmlIgnore funciona igual que JsonIgnore.
  • XmlElementAttribute.ElementName alterará el nombre de la propiedad Json.
  • XmlType.AnonymousType evitará que los objetos se impriman a Json (XmlContractResolver.SuppressAnonymousType, la propiedad altera este comportamiento). Esto es un poco intrincado, ya que tuve que aprender los aspectos internos de Json.Net.

Podría crear una resolución de contratos personalizada que le permitiría realizar ajustes en las propiedades y configurarlas para ignorar dónde se establece un 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; } } } 

Puede usar la aplicación de esta resolución personalizada configurando la propiedad ContractResolver de JsonSerializerSettings al serializar un objeto

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() } ); 

Si está utilizando WebApi, puede configurarlo globalmente para que se aplique a todos los contratos.

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

La clase a continuación se puede usar para serializar (y deserializar) partes del árbol de objetos a XML y luego a JSON.

Uso

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

Clase 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(); } } }