Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将.Net对象序列化为json,使用xml属性进行控制_C#_Xml Serialization_Json.net - Fatal编程技术网

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

C# 将.Net对象序列化为json,使用xml属性进行控制,c#,xml-serialization,json.net,C#,Xml Serialization,Json.net,我有一个.Net对象,我一直在将它序列化为Xml,并用Xml属性修饰它。我现在想将同一个对象序列化为Json,最好使用库 我想直接从内存中的.Net对象转换为Json字符串(不需要先序列化为Xml)。我不希望向类添加任何Json属性,而是希望Json序列化程序使用现有的Xml属性 public class world{ [XmlIgnore] public int ignoreMe{ get; } [XmlElement("foo")] public int bar{ get;

我有一个.Net对象,我一直在将它序列化为Xml,并用Xml属性修饰它。我现在想将同一个对象序列化为Json,最好使用库

我想直接从内存中的.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

结果表明,这不是Newtonsoft Json.Net库的现有功能。我已经编写了一个补丁并将其上载到(存档链接):

这考虑到以下几点:

  • XmlIgnore的工作原理与JsonIgnore一样
  • XmlElementAttribute.ElementName将更改Json属性名
  • XmlType.AnonymousType将禁止将对象打印到Json(XmlContractResolver.SuppressAnonymousType属性会改变此行为)这有点不太成熟,因为我必须在学习Json.Net的内部结构的过程中学习

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

      用法

      [JsonObject]
      public class ClassToSerializeWithJson
      {
          [JsonProperty]
          public TypeThatIsJsonSerializable PropertySerializedWithJsonSerializer {get; set; }
      
          [JsonProperty]
          [JsonConverter(typeof(JsonXmlConverter<TypeThatIsXmlSerializable>))]
          public TypeThatIsXmlSerializable PropertySerializedWithCustomSerializer {get; set; }
      }
      
      [JsonObject]
      公共类ClassToSerializeWithJson
      {
      [JsonProperty]
      具有JSONSerializer{get;set;}的JSONSerialized属性的公共类型
      [JsonProperty]
      [JsonConverter(typeof(JsonXmlConverter))]
      具有XmlSerializable 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();
              }
          }
      }
      
      公共类JsonXmlConverter:JsonConverter,其中TType:class
      {
      私有静态只读XmlSerializer XmlSerializer=新XmlSerializer(typeof(TType));
      公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
      {
      var xml=ToXml(值为TType);
      使用(var stream=newstringreader(xml))
      {
      var xDoc=XDocument.Load(流);
      var json=JsonConvert.SerializeXNode(xDoc);
      WriteRawValue(json);
      }
      }
      公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
      {
      if(reader.TokenType==JsonToken.Null)
      { 
      //使用“null”标记将读取器设置为正确状态
      JToken.Load(读卡器);
      返回null;
      }
      var jObj=JObject.Load(读卡器);
      var json=jObj.ToString();
      var xDoc=JsonConvert.DeserializeXNode(json);
      var xml=xDoc.ToString();
      从xml(xml)返回;
      }
      public override bool CanRead=>true;
      公共覆盖布尔CanConvert(Type objectType)=>objectType==typeof(TType);
      私有静态TType FromXml(字符串xmlString)
      {
      使用(StringReader=新的StringReader(xmlString))
      返回(TType)xmlSerializer.Deserialize(读取器);
      }
      私有静态字符串ToXml(t类型obj)
      {
      使用(StringWriter=新StringWriter())
      使用(XmlWriter=XmlWriter.Create(writer))
      {
      XmlSerializerNamespaces ns=新的XmlSerializerNamespaces();
      ns.Add(String.Empty,String.Empty);
      serializer.Serialize(xmlWriter,obj,ns);
      返回writer.ToString();
      }
      }
      }
      
      您可以创建一个自定义协定解析程序,允许您对属性进行调整,并在设置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属性来使用应用此自定义解析器

      如果您使用的是WebApi,您可以将其全局设置为应用于所有合同

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

      不幸的是,这并不能回答这个问题。我不愿意在我的POCO中添加更多的属性-我有数百个属性和数千个属性,我希望避免在属性名称更改时有两个地方需要修改的解决方案。好的,用您的这个要求更新这个问题,以便人们能够作出贡献。顺便说一句,我投了反对票,是你吗?这已经有几个月了,但是如果你担心过度装饰你的POCO,为什么不为你的json属性使用视图模型呢?我用这个,我的POCO保持干净整洁。谢谢你,帮了我的忙!Newtonsoft Json.Net“在确定如何序列化和反序列化Json时,还会查找DataContract和DataMember属性”。有人知道XmlElementAttributes等是否可以与DataContractAttributes互操作吗?序列化程序可以实现两个属性的序列化,但我想这取决于序列化程序。。。(另请参阅)我为Json.Net编写了一个小补丁,它允许DefaultContractResolver处理Xml属性。它适用于上面的简单示例,但在发布它之前,我需要为更复杂的示例(AnonymousType等)编写更多的测试。万一有人遇到这个问题,它没有进入Json.NET的源代码。我很想听到任何其他解决方案。我个人喜欢添加选择要使用的序列化程序的想法,以及潜在的顺序(正如James在本期中提到的)。我相信存档的补丁现在就在这里:。如果您演示如何使用此类,那会很酷。不管怎样,酷的解决方案+1。@HimBromBeere这有帮助吗?是的,确实有帮助。
      var config = GlobalConfiguration.Configuration;
      var jsonSettings = config.Formatters.JsonFormatter.SerializerSettings;
      jsonSettings.ContractResolver = new CustomContractResolver();