json.net使用JsonConvert.SerializeObject为输出添加注释

时间:2017-05-02 15:41:11

标签: c# json xml json.net

如何删除创建的json字符串底部的注释?

我正在尝试使用Json.net将xml转换为json。具体来说,我从Zillow API获取数据,该数据返回XML,我需要将其作为json字符串传递给Web浏览器。感谢您在本网站上找到的问题/答案,我已经能够在我的c#页面中使用json.net进行转换,但是...

我使用以下内容将我的xml转换为json:

public String GetJson(XmlDocument xml)
{
    return Newtonsoft.Json.JsonConvert.SerializeObject(xml);
}

我成功获得了一个json格式的String,但这个注释添加在json的底部(似乎是一个时间戳)。

{
... json-formatted output...
/* H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda */
}

我检查了原始的xml以验证评论不存在,所以我得出结论它是由json.net添加的。我已经搜索过这个网站 - 以及谷歌 - 以获取有关此信息的信息,但我找不到合适的搜索令牌来查找此评论的任何内容。

谢谢!

1 个答案:

答案 0 :(得分:1)

在序列化XmlDocument时,Json.NET无法插入硬编码的comment - 在XmlNodeConverter中没有任何逻辑可以执行此操作。唯一一次XmlNodeConverter编写注释的时间是在XML DOM层次结构中实际遇到类型为XmlNodeType.Comment的XML节点,在源代码中的1502附近:

            case XmlNodeType.Comment:
                if (writePropertyName)
                {
                    writer.WriteComment(node.Value);
                }
                break;

因此,只有几种方法可以将这样的注释字符串添加到您的JSON输出中,包括:

  1. 您的XML中实际上可能有comments,由Zillow API或您自己的应用程序在其代码堆栈中的某处添加。例如,给定以下XML:

    <?xml version="1.0" encoding="utf-8" ?>
    <root>
        <childNode>
            <innerChildNode>Some Text</innerChildNode>
        </childNode>
        <!-- H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda  --> 
    </root>
    <!-- H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda  -->
    

    Json.NET将生成以下JSON:

    {
      "?xml": {
        "@version": "1.0",
        "@encoding": "utf-8"
      },
      "root": {
        "childNode": {
          "innerChildNode": "Some Text"
        }/* H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda  */
      }/* H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda  */
    }
    
  2. 在代码堆栈的某处,您的应用可能已在JsonConvert.DefaultSettings中安装了自己的XmlNodeConverter版本,该注释会在输出中插入注释。例如,给定以下全局转换器:

    JsonConvert.DefaultSettings = () => new JsonSerializerSettings
    {
        Converters = { new FixedXmlNodeConverter() },
    };
    
    public class FixedXmlNodeConverter : Newtonsoft.Json.Converters.XmlNodeConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            base.WriteJson(writer, value, serializer);
            writer.WriteComment("Global Comment: H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda");
        }
    }
    

    生成的JSON将包含额外的注释:

    {
      "?xml": {
        "@version": "1.0",
        "@encoding": "utf-8"
      },
      "root": {
        "childNode": {
          "innerChildNode": "Some Text"
        }/* H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda  */
      }/* H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda  */
    }/*Global Comment: H:011  T:134ms  S:1206  R:Tue May 02 07:59:03 PDT 2017  B:5.0.42642-master.3acb9f9~hotfix_pre.b72ccda*/
    
  3. 您可能正在使用自己的自定义版本的Json.NET以及XmlNodeConverter的自定义版本。

  4. 示例fiddle展示了前两种可能性。

    如果您的XML中确实有评论节点,则可以按照How to remove all comment tags from XmlDocument中的一个建议或任意数量的类似问题来删除它们。如果您安装了全局转换器,则可以通过手动分配XmlNodeConverter并将其传递给JsonConvert.SerializeObject()来取代它。

    要处理这两种情况,您的GetJson()可能会成为:

        public String GetJson(XmlDocument xml)
        {
            XmlNodeList list = xml.SelectNodes("//comment()");
            foreach(XmlNode node in list)
            {
                node.ParentNode.RemoveChild(node);
            }
    
            var converter = new Newtonsoft.Json.Converters.XmlNodeConverter();
            // Use Newtonsoft.Json.Formatting.None in your production code
            return Newtonsoft.Json.JsonConvert.SerializeObject(xml, Newtonsoft.Json.Formatting.Indented, converter);
        }       
    

    示例fiddle

    如果您使用自己的Json.NET自定义版本,则需要调查并修复发生这种情况的原因。

    如果出于某种原因无法修改传入的XmlDocument(或无法修复Json.NET的自定义版本),您可以继承JsonTextWriter并覆盖WriteComment(可能{{3}虽然这里不需要)并让它们什么都不做:

    public class NoCommentJsonTextWriter : JsonTextWriter
    {
        public NoCommentJsonTextWriter(TextWriter writer)
            : base(writer)
        {
        }
    
        public override void WriteComment(string text)
        {
        }
    }
    

    然后按如下方式使用:

        public String GetJson(XmlDocument xml)
        {
            var sb = new StringBuilder();
            using (var textWriter = new StringWriter(sb))
            // Use Newtonsoft.Json.Formatting.None in your production code
            using (var writer = new NoCommentJsonTextWriter(textWriter) { Formatting = Newtonsoft.Json.Formatting.Indented })
            {
                JsonSerializer.CreateDefault().Serialize(writer, xml);
            }
            return sb.ToString();
        }       
    

    示例WriteCommentAsync