1 people like it.

Using Utf8JsonReader from System.Text.Json with FSharp

High-performance JSON parsing with System.Text.Json and F#

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
// Example translated to F# from 
// https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/use-utf8jsonreader
#r "nuget:System.Text.Json"

open System
open System.Text
open System.Text.Json

let options = JsonReaderOptions(
                AllowTrailingCommas = true, 
                CommentHandling = JsonCommentHandling.Skip)

let readJson (jsonUtf8Bytes:ReadOnlySpan<byte>) =
    let reader = Utf8JsonReader(jsonUtf8Bytes, options)

    while reader.Read() do
        Console.WriteLine reader.TokenType
        match reader.TokenType with
        | JsonTokenType.PropertyName
        | JsonTokenType.String ->
            let text = reader.GetString()
            Console.Write " "
            Console.Write text
        | JsonTokenType.Number ->
            let intValue = reader.GetInt32()
            Console.Write " "
            Console.Write intValue
        | JsonTokenType.None | JsonTokenType.Null | JsonTokenType.Comment 
        | JsonTokenType.True | JsonTokenType.False
        | JsonTokenType.StartObject | JsonTokenType.EndObject
        | JsonTokenType.StartArray  | JsonTokenType.EndArray 
        | _ -> () // Other token types elided for brevity

    Console.WriteLine()

let sampleJson = 
    let jsonBytes = 
        """{ "x": 3 }""" 
        |> Encoding.UTF8.GetBytes
    readJson (System.ReadOnlySpan jsonBytes)
    
namespace System
namespace System.Text
namespace System.Text.Json
val options : JsonReaderOptions
[<Struct>]
type JsonReaderOptions =
  val ``<AllowTrailingCommas>k__BackingField`` : bool
  member AllowTrailingCommas : bool
  member CommentHandling : JsonCommentHandling
  member MaxDepth : int
type JsonCommentHandling =
  | Disallow = 0uy
  | Skip = 1uy
  | Allow = 2uy
field JsonCommentHandling.Skip: JsonCommentHandling = 1uy
val readJson : jsonUtf8Bytes:ReadOnlySpan<byte> -> unit
val jsonUtf8Bytes : ReadOnlySpan<byte>
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)

--------------------
[<Struct>]
type byte = Byte

--------------------
type byte<'Measure> =
  byte
val reader : Utf8JsonReader
Utf8JsonReader.Read() : bool
type Console =
  static member Beep : unit -> unit + 1 overload
  static member CheckNonNull : obj: obj * paramName: string -> unit
  static member Clear : unit -> unit
  static member CreateOutputWriter : outputStream: Stream -> TextWriter
  static member EnsureInitialized<'T (requires reference type)> : field: byref<'T> * initializer: Func<'T> -> 'T
  static member HandleBreakEvent : controlKey: ConsoleSpecialKey -> bool
  static member MoveBufferArea : sourceLeft: int * sourceTop: int * sourceWidth: int * sourceHeight: int * targetLeft: int * targetTop: int -> unit + 1 overload
  static member OpenStandardError : unit -> Stream + 1 overload
  static member OpenStandardInput : unit -> Stream + 1 overload
  static member OpenStandardOutput : unit -> Stream + 1 overload
  ...
Console.WriteLine() : unit
   (+0 other overloads)
Console.WriteLine(value: string) : unit
   (+0 other overloads)
Console.WriteLine(value: obj) : unit
   (+0 other overloads)
Console.WriteLine(value: uint64) : unit
   (+0 other overloads)
Console.WriteLine(value: int64) : unit
   (+0 other overloads)
Console.WriteLine(value: uint32) : unit
   (+0 other overloads)
Console.WriteLine(value: int) : unit
   (+0 other overloads)
Console.WriteLine(value: float32) : unit
   (+0 other overloads)
Console.WriteLine(value: float) : unit
   (+0 other overloads)
Console.WriteLine(value: decimal) : unit
   (+0 other overloads)
property Utf8JsonReader.TokenType: JsonTokenType with get
type JsonTokenType =
  | None = 0uy
  | StartObject = 1uy
  | EndObject = 2uy
  | StartArray = 3uy
  | EndArray = 4uy
  | PropertyName = 5uy
  | Comment = 6uy
  | String = 7uy
  | Number = 8uy
  | True = 9uy
  ...
field JsonTokenType.PropertyName: JsonTokenType = 5uy
field JsonTokenType.String: JsonTokenType = 7uy
val text : string
Utf8JsonReader.GetString() : string
Console.Write(value: string) : unit
   (+0 other overloads)
Console.Write(value: obj) : unit
   (+0 other overloads)
Console.Write(value: uint64) : unit
   (+0 other overloads)
Console.Write(value: int64) : unit
   (+0 other overloads)
Console.Write(value: uint32) : unit
   (+0 other overloads)
Console.Write(value: int) : unit
   (+0 other overloads)
Console.Write(value: float32) : unit
   (+0 other overloads)
Console.Write(value: decimal) : unit
   (+0 other overloads)
Console.Write(value: float) : unit
   (+0 other overloads)
Console.Write(buffer: char []) : unit
   (+0 other overloads)
field JsonTokenType.Number: JsonTokenType = 8uy
val intValue : int
Utf8JsonReader.GetInt32() : int
field JsonTokenType.None: JsonTokenType = 0uy
field JsonTokenType.Null: JsonTokenType = 11uy
field JsonTokenType.Comment: JsonTokenType = 6uy
field JsonTokenType.True: JsonTokenType = 9uy
field JsonTokenType.False: JsonTokenType = 10uy
field JsonTokenType.StartObject: JsonTokenType = 1uy
field JsonTokenType.EndObject: JsonTokenType = 2uy
field JsonTokenType.StartArray: JsonTokenType = 3uy
field JsonTokenType.EndArray: JsonTokenType = 4uy
val sampleJson : unit
val jsonBytes : byte []
type Encoding =
  interface ICloneable
  new : unit -> unit + 2 overloads
  member Clone : unit -> obj
  member DecodeFirstRune : bytes: ReadOnlySpan<byte> * value: byref<Rune> * bytesConsumed: byref<int> -> OperationStatus
  member EncodeRune : value: Rune * bytes: Span<byte> * bytesWritten: byref<int> -> OperationStatus
  member Equals : value: obj -> bool
  member GetBestFitBytesToUnicodeData : unit -> char []
  member GetBestFitUnicodeToBytesData : unit -> char []
  member GetByteCount : chars: char [] -> int + 6 overloads
  member GetByteCountFast : pChars: nativeptr<char> * charsLength: int * fallback: EncoderFallback * charsConsumed: byref<int> -> int
  ...
property Encoding.UTF8: Encoding with get
Encoding.GetBytes(s: string) : byte []
Encoding.GetBytes(chars: char []) : byte []
Encoding.GetBytes(chars: ReadOnlySpan<char>, bytes: Span<byte>) : int
Encoding.GetBytes(s: string, index: int, count: int) : byte []
Encoding.GetBytes(chars: char [], index: int, count: int) : byte []
Encoding.GetBytes(chars: nativeptr<char>, charCount: int, bytes: nativeptr<byte>, byteCount: int) : int
Encoding.GetBytes(s: string, charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
Encoding.GetBytes(chars: char [], charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
Raw view Test code New version

More information

Link:http://fssnip.net/8a9
Posted:1 year ago
Author:Tuomas Hietanen
Tags: json , parsing , reader , text