Skip to content

处理重复引用

陈鑫伟 edited this page May 20, 2019 · 4 revisions

这里提供 Swifter.Json 处理重复引用的四种方式。

使用说明等都在如下的注释里。

这里没有提供建议的操作,我本人建议是不要序列化有循环引用的对象,因为 Json 本身不支持此操作。

您可以在开发时使用方式四抛出异常来提醒开发人员,然后再发布时再关闭该功能。

    public class Demo
    {
        public int HashCode => GetHashCode();

        public object Parent { get; set; }

        public object Me => this;
        
        public object Child { get; set; }

        public static void Main()
        {
            var obj = new Demo();
            var chi = new Demo();

            obj.Child = chi;
            chi.Parent = obj;

            // 处理方式一:将循环引用的对象设为 Null。
            var jsonFormatter = new JsonFormatter(JsonFormatterOptions.LoopReferencingNull | JsonFormatterOptions.Indented);

            Console.WriteLine(jsonFormatter.Serialize(obj));
            /*
             * {
             *   "Child": {
             *     "Child": null,
             *     "HashCode": 30015890,
             *     "Me": null,
             *     "Parent": null
             *   },
             *   "HashCode": 55530882,
             *   "Me": null,
             *   "Parent": null
             * }
            **/

            // 配合忽略 Null 使用将会忽略循环引用的字段。
            jsonFormatter.Options |= JsonFormatterOptions.IgnoreNull;

            Console.WriteLine(jsonFormatter.Serialize(obj));
            /*
             * {
             *   "Child": {
             *     "HashCode": 30015890,
             *   },
             *   "HashCode": 55530882
             * }
            **/

            // 处理方式二:将重复引用以 $ref 形式序列化。
            // 此方式符合 Json 格式,但不是 Json 标准。
            // 许多 Json 编辑工具都承认 $ref 格式,如 VS。
            // 注意:此方式可能无法在浏览器中处理。
            jsonFormatter = new JsonFormatter(JsonFormatterOptions.MultiReferencingReference | JsonFormatterOptions.Indented);

            Console.WriteLine(jsonFormatter.Serialize(obj));
            /*
             * {
             *   "Child": {
             *     "Child": null,
             *     "HashCode": 30015890,
             *     "Me": { "$ref": "#/Child" },
             *     "Parent": { "$ref": "#" }
             *   },
             *   "HashCode": 55530882,
             *   "Me": { "$ref": "#" },
             *   "Parent": null
             * }
            **/

            // 处理方式三:设置最大结构深度。

            jsonFormatter = new JsonFormatter(JsonFormatterOptions.Indented | JsonFormatterOptions.IgnoreNull);

            jsonFormatter.MaxDepth = 2;
            
            Console.WriteLine(jsonFormatter.Serialize(obj));
            /*
             * {
             *   "Child": {
             *     "HashCode": 30015890,
             *     "Me": {
             *     },
             *     "Parent": {
             *     }
             *   },
             *   "HashCode": 55530882,
             *   "Me": {
             *     "Child": {
             *     },
             *     "HashCode": 55530882,
             *     "Me": {
             *     }
             *   }
             * }
            **/

            // 处理方式四:抛出异常

            jsonFormatter = new JsonFormatter(JsonFormatterOptions.LoopReferencingException);

            Console.WriteLine(jsonFormatter.Serialize(obj));
            // JsonLoopReferencingException: Json serializating members '#/Child' and '#/Child/Me' loop referencing.
        }
    }