【问题标题】:json.net using JsonConvert.SerializeObject adds a comment to outputjson.net 使用 JsonConvert.SerializeObject 在输出中添加注释
【发布时间】:2017-05-02 15:41:10
【问题描述】:

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

我正在尝试使用 Json.net 将 xml 转换为 json。具体来说,我从 Zillow API 获取数据,该 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 添加的。我已经在这个网站和谷歌上搜索了这方面的信息,但我没有找到正确的搜索令牌来找到任何提及此评论的内容。

谢谢!

【问题讨论】:

标签: c# json xml json.net


【解决方案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 版本,该版本将cmets 插入到输出中。例如,给定以下全局转换器:

    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 将包含额外的 cmets:

    {
      "?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

示例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(可能还有 WriteCommentAsync,尽管这里不需要)让他们什么都不做:

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

示例fiddle

【讨论】:

  • 这是第 1 项;评论在 xml 中,但不在 json 中的同一个位置(至少当我在控制台窗口中查看 xml 时)。感谢您的彻底回答,@dbc,您实际上帮助我解决了这个描述的另一个问题.
猜你喜欢
  • 1970-01-01
  • 2011-05-28
  • 1970-01-01
  • 2014-10-03
  • 1970-01-01
  • 2014-01-18
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
相关资源
最近更新 更多