百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
J

Jil

> 编程语言
开源

基于 Sigil 构建的快速 .NET JSON (De) 序列化器

2.1K stars0 点赞0 次浏览
访问官网GitHub

工具介绍

基于 Sigil 构建的快速 .NET JSON (De) 序列化器

### Jil A fast JSON (de)serializer, built on [Sigil](https://github.com/kevin-montrose/Sigil) with a number of somewhat crazy optimization tricks. [Releases are available on Nuget](https://www.nuget.org/packages/Jil/) in addition to this repository. ## Usage ### Serializing ```C# using(var output = new StringWriter()) { JSON.Serialize( new { MyInt = 1, MyString = "hello world", // etc. }, output ); } ``` There is also a `Serialize` method that returns a string. The first time Jil is used to serialize a given configuration and type pair, it will spend extra time building the serializer. Subsequent invocations will be much faster, so if a consistently fast runtime is necessary in your code you may want to "prime the pump" with an earlier "throw away" serialization. ### Dynamic Serialization If you need to serialize compile-time unknown types (including subclasses, and virtual properties) you should use `JSON.SerializeDynamic` instead. `JSON.SerializeDynamic` does not require a generic type parameter, and can cope with subclasses, `object`/`dynamic` members, and [DLR](http://msdn.microsoft.com/en-us/library/dd233052(v=vs.110).aspx) participating types such as [ExpandoObject](http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject(v=vs.110).aspx) and [DynamicObject](http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject(v=vs.110).aspx). ### Deserializing ```C# using(var input = new StringReader(myString)) { var result = JSON.Deserialize(input); } ``` There is also a `Deserialize` method that takes a string as input. The first time Jil is used to deserialize a given configuration and type pair, it will spend extra time building the deserializer. Subsequent invocations will be much faster, so if a consistently fast runtime is necessary in your code you may want to "prime the pump" with an earlier "throw away" deserialization. Jil is case sensitive as a rule, so when deserializing make sure your member names match what is in your JSON. ### Dynamic Deserialization ```C# using(var input = new StringReader(myString)) { var result = JSON.DeserializeDynamic(input); } ``` There is also a `DeserializeDynamic` method that works directly on strings. These methods return `dynamic`, and support the following operations: - Casts * ie. `(int)JSON.DeserializeDynamic("123")` - Member access * ie. `JSON.DeserializeDynamic(@"{""A"":123}").A` - Indexers * ie. `JSON.DeserializeDynamic(@"{""A"":123}")["A"]` * or `JSON.DeserializeDynamic("[0, 1, 2]")[0]` - Foreach loops * ie. `foreach(var keyValue in JSON.DeserializeDynamic(@"{""A"":123}")) { ... }` - in this example, `keyValue` is a dynamic with `Key` and `Value` properties * or `foreach(var item in JSON.DeserializeDynamic("[0, 1, 2]")) { ... }` - in this example, `item` is a `dynamic` and will have values 0, 1, and 2 - Common unary operators (+, -, and !) - Common binary operators (&&, ||, +, -, *, /, ==, !=, <, <=, >, and >=) - `.Length` & `.Count` on arrays - `.ContainsKey(string)` on objects ## Supported Types Jil will only (de)serialize types that can be reasonably represented as [JSON](http://json.org). The following types (and any user defined types composed of them) are supported: - Strings (including char) - Booleans - Integer numbers (int, long, byte, etc.) - Floating point numbers (float, double, and decimal) - DateTimes & DateTimeOffsets * Note that DateTimes are converted to UTC time to allow for round-tripping, use DateTimeOffsets if you need to preserve timezone information * See Configuration for further details - TimeSpans * See Configuration for further details - Nullable types - Enumerations * Including \[Flags\] - Guids * Only the ["D" format](http://msdn.microsoft.com/en-us/library/97af8hh4.aspx) - IList<T>, ICollection<T>, and IReadOnlyList<T> implementations - IDictionary<TKey, TValue> implementations where TKey is a string or enumeration - ISet<T> Jil deserializes public fields and properties; the order in which they are serialized is not defined (it is unlikely to be in declaration order). The [`DataMemberAttribute.Name` property](http://msdn.microsoft.com/en-us/library/ms584759(v=vs.110).aspx) and [`IgnoreDataMemberAttribute`](http://msdn.microsoft.com/en-us/library/system.runtime.serialization.ignoredatamemberattribute.aspx) are respected by Jil, as is the [ShouldSerializeXXX() pattern](http://msdn.microsoft.com/en-us/library/53b8022e(v=vs.110).aspx). For situations where `DataMemberAttribute` and `IgnoreDataMemberAttribute` cannot be used, Jil provides the [`JilDirectiveAttribute`](https://github.com/kevin-montrose/Jil/blob/master/Jil/JilDirectiveAttribute.cs) which provides equivalent functionality. Strong typing of primitives types (int, long, etc.) can be done by annotating a wrapper type with `[JilPrimitiveWrapper]`. Such a type should have one declared field or property, and default or single parameter constructor. ## Unions Jil has limited support for "unions" (fields on JSON objects that may contain one of several types), provided that they can be distiguished by their first character. In other words: ```csharp class LegalUnion { [JilDirective(Name = "Foo", IsUnion = true)] public string FooString { get; set; } [JilDirective(Name = "Foo", IsUnion = true)] public int FooInt { get; set; } } ``` Is allowed because the first character of a JSON string is always `"`, while the first character of a JSON number is a digit or `-`. The following would not be legal, however. ```csharp class IllegalUnion { [JilDirective(Name = "Foo", IsUnion = true)] public uint FooUInt { get; set; } [JilDirective(Name = "Foo", IsUnion = true)] public double FooDouble { get; set; } } ``` Since both properties could start with a digit. You can also use a `Type` member to determine which field was (de)serialized. ```csharp class WithUnionType { [JilDirective(Name = "Foo", IsUnion = true, IsUnionType = true)] public Type FooType { get; set; } [JilDirective(Name = "Foo", IsUnion = true)] public uint FooUInt { get; set; } [JilDirective(Name = "Foo", IsUnion = true)] public List FooList { get; set; } } ``` When serializing this field _must_ be set. ## Configuration Jil's `JSON.Serialize` and `JSON.Deserialize` methods take an optional `Options` parameter which controls: - The format of DateTimes, DateTimeOffsets, and TimeSpans; one of * MicrosoftStyleMillisecondsSinceUnixEpoch, a string - "\/Date(##...##)\/" for DateTimes & DateTimeOffsets - "1.23:45:56.78" for TimeSpans * MillisecondsSinceUnixEpoch, a number - for DateTimes & DateTimeOffsets it can be passed directly to [JavaScript's Date() constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) - for TimeSpans it's simply [TimeSpan.TotalMilliseconds](http://msdn.microsoft.com/en-us/library/system.timespan.totalmilliseconds%28v=vs.110%29.aspx) * SecondsSinceUnixEpoch, a number - for DateTimes & DateTimeOffsets this is commonly refered to as [unix time](http://en.wikipedia.org/wiki/Unix_time) - for TimeSpans it's simply [TimeSpan.TotalSeconds](http://msdn.microsoft.com/en-us/library/system.timespan.totalseconds%28v=vs.110%29.aspx) * ISO8601, a string - for DateTimes & DateTimeOffsets, ie. "2011-07-14T19:43:37Z" * DateTimes are always serialized in UTC (timezone offset = 00:00), because Local DateTimes cannot reliably roundtrip * DateTimeOffsets include their timezone offset when serialized - for TimeSpans, ie. "P40DT11H10M9.4S" * RFC1123, a string - for DateTimes and DateTimeOffsets, ie. "Thu, 10 Apr 2008 13:30:00 GMT" - "1.23:45:56.78" for TimeSpans - What to treat DateTimes with an [Unspecified DateTimeKind](https://msdn.microsoft.com/en-us/library/shx7s921%28v=vs.110%29.aspx) as; one of * IsLocal, will treat an unspecified DateTime as if it were in local time * IsUtc, will treat an unspecified DateTime as if it were in UTC - Whether or not to exclude null values when serializing dictionaries, and object members - Whether or not to "pretty print" while serializing, which adds extra linebreaks and whitespace for presentation's sake - Whether or not the serialized JSON will be used as JSONP (which requires slightly more work be done w.r.t. escaping) - Whether or not to include inherited members when serializing - The way to format member names; one of * Verbatim - As it appears in source, unless modified by a `[MemberName]` or `[JilDirective]` * CamelCase - lowercasing the first letter of members, ie. `"CamelCase"` would become `"camelCase"` ## Benchmarks Jil aims to be the fastest general purpose JSON (de)serializer for .NET. Flexibility and "nice to have" features are explicitly discounted in the pursuit of speed. These benchmarks were run on a machine with the following specs:
  • Operating System: Windows 8.1 Enterprise 64-bit (6.3, Build 9600) (9600.winblue_r3.140827-1500)
  • System Manufacturer: Apple Inc.
  • System Model: MacBookPro11,3
  • Processor: Intel(R) Core(TM) i7-4960HQ CPU @ 2.60GHz (8 CPUs), ~2.6GHz
  • Memory: 16384MB RAM
    • DDR3
    • Dual Channel
    • 798.1 MHZ
As with all benchmarks, take these with a grain of salt. ### Serialization For comparison, here's how Jil stacks up against other popular .NET serializers in a [synthetic benchmark](https://github.com/kevin-montrose/Jil/tree/7915b2e8897024e82628c514d63af596fcfd5013/Benchmark): - [Json.NET](http://james.newtonking.com/json) - JSON library included with ASP.NET MVC, version 6.0.7 - [ServiceStack.Text](https://github.com/ServiceStack/ServiceStack.Text) - JSON, CSV, and JSV library; a part of the [ServiceStack framework](https://github.com/ServiceStack/ServiceStack), version 3.9.71 - [protobuf-net](https://code.google.com/p/protobuf-net/) - binary serializer for Google's [Protocol Buffers](https://code.google.com/p/protobuf/), version 2.0.0.688 * __does not__ serialize JSON, included as a baseline All three libraries are in use at [Stack Exchange](https://stackexchange.com/) in various production roles. Note that the bars in each group of each graph are scaled so that the fastest library is 100. Numbers, include millisecond timings, can found in [this Google Document](https://docs.google.com/spreadsheets/d/1Jx7DAGopJo3BC0St_L5qHJJrWpZe9x9BCHgdeY9-b-w/edit). The Question, Answer, and User types are taken from the [Stack Exchange API](http://api.stackexchange.com/). Data for each type is randomly generated from a fixed seed. Random text is biased towards ASCII*, but includes all unicode. *This is meant to simulate typical content from the Stack Exchange API. ### Deserialization The same libraries and same types were used to test deserialization. Note that the bars in each group of each graph are scaled so that the fastest library is 100. Numbers, include millisecond timings, can be found in [the same Google Document](https://docs.google.com/spreadsheets/d/1Jx7DAGopJo3BC0St_L5qHJJrWpZe9x9BCHgdeY9-b-w/edit). ## Tricks Jil has a lot of tricks to make it fast. These may be interesting, even if Jil itself is too limited for your use. ### Sigil Jil does a lot of IL generation to produce tight, focused code. While possible with [ILGenerator](http://msdn.microsoft.com/en-us/library/system.reflection.emit.ilgenerator.aspx), Jil instead uses the [Sigil library](https://github.com/kevin-montrose/Sigil). Sigil automatically does a lot of the busy work you'd normally have to do manually to produce ideal IL. Using Sigil also makes hacking on Jil much more productive, as debuging IL generation without it is pretty slow going. ### Trade Memory For Speed Jil's internal serializers and deserial

Issues· 0 开放

查看全部 Issues在 GitHub 打开

暂无开放 Issues,或尚未同步最近议题。

> 标签

C#

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年8月1日
最后更新2026年9月17日
分类编程语言
定价开源

> 相关工具

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言