Skip to content

Instantly share code, notes, and snippets.

@thinkbeforecoding
Created August 9, 2013 12:37
Show Gist options
  • Save thinkbeforecoding/6193297 to your computer and use it in GitHub Desktop.
Save thinkbeforecoding/6193297 to your computer and use it in GitHub Desktop.
JObj for Newtonsoft.Json in F#
module Json
open System
open Newtonsoft.Json
type JObj =
| JNull
| JInt of int64
| JString of string
| JFloat of float
| JBool of bool
| JDate of DateTime
| JArray of JObj list
| JObj of (string * JObj) list
module private IO =
let createReader text = new JsonTextReader( new IO.StringReader(text))
let tokenType (reader: JsonReader) = reader.TokenType
let read (reader: JsonReader) = reader.Read()
let value (reader: JsonReader) = unbox reader.Value
let jdate (reader: JsonReader) = reader.ReadAsDateTime()
open IO
let jstr s = JString s
let jint i = JInt i
let Jfloat f = JFloat f
let jbool b = JBool b
let toJArray f l = JArray(l |> List.map f)
// StartConstructor,
// Raw,
// EndConstructor,
// Bytes,
let rec private build reader =
let value =
match tokenType reader with
| JsonToken.Null -> JNull
| JsonToken.Undefined -> JNull
| JsonToken.String -> JString(value reader)
| JsonToken.Integer -> JInt(value reader)
| JsonToken.Float -> JFloat(value reader)
| JsonToken.Boolean -> JBool(value reader)
| JsonToken.StartArray ->
if read reader then
JArray(readArray reader )
else
JArray([])
| JsonToken.StartObject ->
if read reader then
JObj(readObject reader [])
else
JObj([])
| JsonToken.Comment ->
if read reader then
build reader
else
JNull
| JsonToken.Date -> JDate(value reader)
| _ -> JNull
read reader |> ignore
value
and readArray reader =
match tokenType reader with
| JsonToken.EndArray -> []
| _ ->
let value = build reader
value :: readArray reader
and readObject reader props =
match tokenType reader with
| JsonToken.EndObject -> props
| JsonToken.PropertyName ->
let propertyName = value reader
let propertyValue =
if read reader then
build reader
else
JNull
readObject reader ((propertyName, propertyValue) :: props)
| _ -> invalidOp "The unexpected tocken"
let deserialize text =
let reader =
text
|> createReader
if read reader then
reader
|> build
else
JNull
let (|JProp|_|) key props =
let rec scan props head =
match props with
| [] -> None
| (n, v) as p :: tail ->
if n = key then
Some(v, head @ tail)
else
scan tail (p :: head)
scan props []
let (|JProps|_|) keys props =
let rec scan keys r rp =
function
| (n,v) as p :: t ->
if Set.contains n keys then
scan (Set.remove n keys) (v :: r) rp t
else
scan keys r (p :: rp) t
| [] ->
if Set.isEmpty keys then
Some (r, rp)
else
None
scan (Set.ofList keys) [] [] props
let serialize o =
use stringWriter = new IO.StringWriter()
use w = new JsonTextWriter(stringWriter)
let rec serialize o =
let writeProp (name, value) =
w.WritePropertyName(name)
serialize value
match o with
| JNull -> w.WriteNull()
| JInt v -> w.WriteValue(v)
| JFloat v -> w.WriteValue(v)
| JString v -> w.WriteValue(v)
| JBool v -> w.WriteValue(v)
| JDate v -> w.WriteValue(v)
| JArray a ->
w.WriteStartArray()
a |> List.iter serialize
w.WriteEndArray()
| JObj props ->
w.WriteStartObject()
props |> List.iter writeProp
w.WriteEndObject()
serialize o
stringWriter.ToString()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment