65.9K
CodeProject 正在变化。 阅读更多。
Home

Sweet Jayson

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2015年6月8日

CPOL

5分钟阅读

viewsIcon

9828

快速、可靠、易于使用、完全符合 json.org 标准、线程安全的 C# JSON 库,适用于服务器端和桌面操作

引言

互联网上有许多 .NET JSON 库。有些声称小巧,有些声称快速。大多数情况下它们是对的,但可靠性如何呢?深入研究后,你会发现根据你的具体情况,它们会缺少一些东西,而你无法成功使用该库,或者你需要编写越来越多的扩展来处理你的特定情况。忘掉所有这些,试试 Sweet.Jayson

背景

它快速、可靠、易于使用、线程安全且完全符合 json.org 标准。它是从头开始设计和编码的,一直牢记这些,而不是在某个时间点才考虑。

承诺的内容?

Sweet.Jayson JSON 库支持

public class CustomBaseType
{
    public string Label { get; set; }
    public string Ref { get; set; }
    public string SHA { get; set; }
    public List<string> Items { get; set; } 
}

public class CustomType
{ 
    public string State;
    public CustomBaseType Base { get; set; }
}

public static class Program
{
    public static void Main(params string[] args)
    {
        var dto = new CustomType() { 
            { 
                State = "open" 
                Base = new CustomBaseType() 
                    {
                        Label = "technoweenie:master",
                        Ref = "master",
                        SHA = "53397635da83a2f4b5e862b5e59cc66f6c39f9c6",
                        Items = new List<object> { "Dev", "Test", "Prod" }
                    }
            };

        var jsonObj = 
            (Dictionary<string, object>)JaysonConverter.ToJsonObject(dto);
    }
}
  • .NET 3.5、4.0、4.5 和 Mono
  • 任何 POCO 类型序列化/反序列化
  • 默认 .NET 类型 (DateTime, DateTimeOffset, TimeSpan, Guid, ArrayList, Hashtable, HashSet...)
  • 默认和自定义通用 .NET 类型 (List<T>, Dictionary<T,K>, Stack<T>, Queue<T>...)
  • 并发集合类型 (ConcurrentBag<T>, ConcurrentDictionary<T,K>,
    ConcurrentStack<T>, ConcurrentQueue<T>)
  • 任何键类型非 typeof(string) 的字典类型,带有特殊的键值对 ($k, $v) 对象 (IDictionary<int,decimal>, IDictionary, Hashtable...)
  • DataTable, DataSet (以及 自定义 DataSetsDataTable DataSets 中的关系)
  • Nullable 类型 (int?, DateTime?...)
  • 接口,包括默认 .NET 接口和自定义接口 (IList, IList<T>, IMyCustomInterface...)
  • 数组类型 ( 类型) (int[], char[], string[]...)
  • 字节数组 (byte[]) 作为 Base64String
  • 多维数组 (int[,])
  • 交错数组 (int[][])
  • 混合数组 (int[][,]int[,][])
  • dynamic 类型
  • struct 类型,包括序列化和反序列化
  • 没有默认构造函数的类型 (例如 Tuple)
  • 使用 "$type" 表示法嵌入类型信息以进行精确类型反序列化
  • 使用 "$types" 表示法嵌入全局类型信息以进行精确类型反序列化和紧凑输出
  • 包含或排除 "null" 值到/从输出 (在 PropertiesLists 中分开),
  • Guid 序列化为字节数组 (byte[])
  • 区分大小写的/不区分大小写的属性名称
    {
        "state": "open",
        "base": {
            "label": "technoweenie:master",
            "ref": "master",
            "sha": "53397635da83a2f4b5e862b5e59cc66f6c39f9c6"
        }
    }

    {
        "State": "open",
        "Base": {
            "Label": "technoweenie:master",
            "Ref": "master",
            "SHA": "53397635da83a2f4b5e862b5e59cc66f6c39f9c6"
        }
    }
  • 启用/禁用 格式化美化输出(美化打印),而不会损失性能
    {"state"":"open","base"":{"label":"technoweenie:master",
    "ref"":"master","sha"":"53397635da83a2f4b5e862b5e59cc66f6c39f9c6"}}

    {
        "state": "open",
        "base": {
            "label": "technoweenie:master",
            "ref": "master",
            "sha": "53397635da83a2f4b5e862b5e59cc66f6c39f9c6"
        }
    }
  • 使用 System.Runtime.Serialization.SerializationBinder 更改反序列化中的类型,
  • 通过 JaysonTypeOverridePropertyField 名称更改为任何值,而无需使用自定义 Attribute
    var dto1 = TestClasses.GetTypedContainerDto();
    
    JaysonSerializationSettings jaysonSerializationSettings = 
        JaysonSerializationSettings.DefaultClone();
    jaysonSerializationSettings.TypeNames = JaysonTypeNameSerialization.All;
    jaysonSerializationSettings.
        AddTypeOverride(
            new JaysonTypeOverride<TextElementDto>().
                IgnoreMember("ElementType").
                SetMemberAlias("ElementId", "id"));
    
    JaysonDeserializationSettings jaysonDeserializationSettings = 
        JaysonDeserializationSettings.DefaultClone();
    jaysonDeserializationSettings.
        AddTypeOverride(
            new JaysonTypeOverride<TextElementDto, TextElementDto2>()).
        AddTypeOverride(new JaysonTypeOverride<TextElementDto2>().
            SetMemberAlias("ElementId", "id").
            IgnoreMember("ElementType"));
    
    string json = JaysonConverter.ToJsonString(dto1, jaysonSerializationSettings);
    var dto2 = JaysonConverter.ToObject<TypedContainerDto>(json, jaysonDeserializationSettings);
  • 使用 JaysonTypeOverride 更改序列化/反序列化中的类型
  • 通过 JaysonTypeOverride 忽略 FieldProperties
  • 包含或排除只读成员 (Field & Properties) 到/从序列化
  • 匿名类型 序列化/反序列化(只有当类型已存在于当前进程中时,反序列化才可能)
  • 自定义 Number (byte, short, int, long, float, double, decimal, sbyte, ushort, uint, ulong),
    DateTime, DateTimeOffsetTimeSpan 在序列化中的格式
  • 通过 JaysonDateFormatType 进行各种 DateTime 序列化/反序列化格式:Iso8601
    Local date: "1983-10-25T16:00:30.345+0300"
    UTC date: "1983-10-25T13:00:30.345Z"

    Microsoft

    Local date: "/Date(1224043200000+0300)/"
    UTC date: "/Date(1224043200000)/"

    JScript

    Local date: new Date(1224043200000+0300)
    UTC date: new Date(1224043200000)

    UnixEpoch

    Any long number: 1224043200000

    CustomDate

    Any date custom date format defined in serialization settings

    CustomUnixEpoch

    Any custom long number format defined in serialization settings
  • Decimal 值转换为 Double 或将其保留为 Decimal 形式

  • 启用/禁用 AnonymousTypes, DynamicObjectExpandoObject 类型

  • 启用/禁用 Unicode 字符转义
    \u0357
  • 按降序 FieldProperty 名称进行排序
  • 忽略 Circular References 或在遇到 Circular Reference 时抛出异常
  • 使用 Enum 类型名称或数字 Enum
  • 反序列化中的最大对象深度
  • 使用默认类型(如 Dictionary<string,object>ExpandoObject)进行操作的选项,
    List<object>, ArrayListArray 而不是将对象转换为自定义 .NET 类型
    • 解析 JSON 数组 []List<object>, ArrayListArray 之间转换的选项
    • JSON 对象 {} 解析为 Dictionary<string, object>ExpandoObject 的选项
    {
        "State": "open",
        "Base": {
            "Label": "technoweenie:master",
            "Ref": "master",
            "SHA": "53397635da83a2f4b5e862b5e59cc66f6c39f9c6",
            "Items": [
                "Dev",
                "Test",
                "Prod"
            ]
        }
    }

    将被解析为

    new Dictionary<string, object> { 
        { "State": "open" },
        { "Base": 
            {
                "Label": "technoweenie:master",
                "Ref": "master",
                "SHA": "53397635da83a2f4b5e862b5e59cc66f6c39f9c6",
                "Items": new List<object> { "Dev", "Test", "Prod" }
            }
        }
    };
  • 使用 JaysonObjectActivator 在转换过程外创建自定义对象
  • 使用
    JaysonConverter.ToJsonObject 函数将任何 .NET 对象转换为 Dictionary<string,object>List<object>
  • 使用 $id$ref 标签进行对象引用,
    {
        "$type": "ObjectToDict.A, ObjectToDict",  
        "$id": 1,  
        "O2": {  
            "1": {  
                "$type": "System.Decimal, mscorlib",  
                "$value": 2  
            },  
            "$id": 2,  
            "a": "b",  
            "true": false,  
            "#self": {  
                "$ref": 2  
            },  
            "#list": {  
                "$type": "System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib",  
                "$id": 3,  
                "$values": [  
                    {  
                        "$ref": 2  
                    }  
                ]  
            }  
        },  
        "O1": true,  
        "E1": "EnumB, EnumC",  
        "D2": 23456.78901,  
        "L2": {  
            "$id": 4,  
            "$values": [  
                1,  
                null,  
                2,  
                null  
            ]  
        },  
        "L1": {  
            "$type": "System.Int64, mscorlib",  
            "$value": 12345678909876544  
        },  
        "D4": {  
            "$ref": 2  
        },  
        "D1": {  
            "$type": "System.Decimal, mscorlib",  
            "$value": 12345.6789  
        },  
        "I1": 123456789  
    }
  • 启用或禁用 Dictionary<?,object>KV 模式
    {  
        "$type": "Sweet.Jayson.Tests.A, Sweet.Jayson.Tests",  
        "D3": {  
            "$type": "System.Collections.Generic.Dictionary`2
            [[System.Object, mscorlib],[System.Object, mscorlib]], mscorlib",  
            "1": {  
                "$type": "System.Decimal, mscorlib",  
                "$value": 2  
            },  
            "a": "b",  
            "True": false  
        }  
    }

    {  
        "$type": "Sweet.Jayson.Tests.A, Sweet.Jayson.Tests",  
        "D3": {  
            "$type": "System.Collections.Generic.Dictionary`2
            [[System.Object, mscorlib],[System.Object, mscorlib]], mscorlib",  
            "$kv": [  
                {  
                    "$k": 1,  
                    "$v": {  
                        "$type": "System.Decimal, mscorlib",  
                        "$value": 2  
                    }  
                },  
                {  
                    "$k": "a",  
                    "$v": "b"  
                },  
                {  
                    "$k": true,  
                    "$v": false  
                }  
            ]  
        }  
    }

关注点

JSON 是一种用于传输对象状态的简化表示法。它简单易用,适用于 JScript、Pyton、Ruby 或任何其他动态语言,但当在静态编译语言中使用时,将其映射和绑定到类会非常痛苦。

不要认为 .NET 库为您提供了市面上最好的选择。大多数情况下,它们旨在支持通用场景并且编码不佳。.NET 是一个很棒的框架,但在每个特定场景下,它都会显得不足。

我的观点是,当您需要性能和稳定性时,您需要尝试自己编写,或者在测试时尝试第三方库。同时,不要认为每个著名的第三方库都很棒。大多数情况下,它们出名只是偶然,或者因为它们是该领域的第一个。因此,您也需要仔细测试它们,并接受它们在很多情况下是成功的,但并非所有情况都如此。但是,如果您也处于这种情况并打算编写自己的库,请记住要为不眠不休的日子做好准备。

该库是在测试了许多第三方库和 .NET 自带的 JSON 序列化和反序列化库后开始的。当它们失败或需要付出太多努力才能满足大多数特定需求时,我感到厌倦,需要编写一个新的库,这就是这个新面孔,并希望分享它,让其他人不必经历同样的痛苦。

如果您在库方面需要任何帮助,请随时与我联系。

历史

v1.0.0.0

  • 2015 年 5 月 3 日,初始发布

v1.0.0.1

  • 2015 年 6 月 6 日,增加了对特殊类型;Stack、Queue 和 Concurrent 列表的支持

v1.0.0.2

  • 2015 年 6 月 6 日,对列表处理进行了小幅修复,当最后一个元素是 null 或布尔值时

v1.0.0.3

  • 2015 年 6 月 8 日,GUID 序列化性能优化

v1.0.0.4

2015 年 6 月 9 日

  • 进行了一些重构
  • 封锁了一些类
  • 实现了错误消息类
  • JaysonError 文件添加了许可证标题

v1.0.0.5

2015 年 6 月 9 日

  • 长数字序列化修复
  • AsciiToLower & AsciiToUpper 修复

v1.0.0.6

2015 年 6 月 10 日

  • 添加了新测试
  • IDictionary<object, object> 键转换修复
  • ConvertToPrimitiveenums 修复

v1.0.0.7

2015 年 6 月 11 日

  • 性能改进
  • 实现了 JaysonOrderedDictionary 以用于成员名称
  • 详细的测试用例

v1.0.0.8

2015 年 6 月 17 日

  • 对象引用支持
  • 性能优化
  • 用于启用/禁用 Dictionary<?,object>KV 模式的设置
  • 详细的测试用例

v1.0.0.9

2015 年 7 月 14 日

  • System.Runtime.Serialization.ISerializable 接口支持
  • System.Type System.Type 序列化支持
  • System.Reflection.ConstructorInfo, System.Reflection.MethodInfo, System.Reflection.PropertyInfoSystem.Reflection.FieldInfo 序列化支持
  • System.Exception 序列化支持
  • 修复了 .Net System.Type.GetType,其工作方式与 Mono 版本不同
  • 详细的测试用例
© . All rights reserved.