Сериализовать .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
}
Ответы
Ответ 1
Оказывается, это была не существующая функция библиотеки Newtonsoft Json.Net. Я написал патч и загрузил его в отслеживание проблем Json.Net
Это позволяет:
- XmlIgnore работает так же, как JsonIgnore.
- XmlElementAttribute.ElementName изменит имя свойства Json.
- XmlType.AnonymousType будет подавлять объекты от печати в Json (свойство XmlContractResolver.SuppressAnonymousType изменяет это поведение), это немного взломанно, так как мне приходилось изучать внутренности Json.Net по мере того, как я шел.
Ответ 2
Используйте [JsonProperty(PropertyName="foo")]
Атрибут и установите PropertyName
.
Ответ 3
Вы можете создать пользовательский разрешитель контрактов, который позволит вам вносить корректировки в свойства и устанавливать их для игнорирования, где установлен 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;
}
}
}
Ответ 4
Следующий класс может использоваться для сериализации (и десериализации) частей дерева объектов в XML, а затем в JSON.
Использование
[JsonObject]
public class ClassToSerializeWithJson
{
[JsonProperty]
public TypeThatIsJsonSerializable PropertySerializedWithJsonSerializer {get; set; }
[JsonProperty]
[JsonConverter(typeof(JsonXmlConverter<TypeThatIsXmlSerializable>))]
public TypeThatIsXmlSerializable PropertySerializedWithCustomSerializer {get; set; }
}
Класс JsonXmlConverter
public class JsonXmlConverter<TType> : 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();
}
}
}