Created
August 9, 2013 12:37
-
-
Save thinkbeforecoding/6193297 to your computer and use it in GitHub Desktop.
JObj for Newtonsoft.Json in F#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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