import gleam/json import gleam/list import gleam/dynamic.{Dynamic} import gleam/result import bison/bson.{Value} import bison/object_id import bison/uuid import bison/md5 import birl/time pub fn doc_to_json(d: Value) -> json.Json { case d { bson.Document(doc) -> { doc |> list.map(fn(itm) { case itm.1 { bson.DateTime(item) -> { #(itm.0, json.string(time.to_naive(item))) } bson.Str(item) | bson.JS(item) -> { #(itm.0, json.string(item)) } bson.Int32(tem) | bson.Int64(tem) | bson.Timestamp(tem) -> { #(itm.0, json.int(tem)) } bson.Double(tem) -> { #(itm.0, json.float(tem)) } bson.Boolean(tem) -> { #(itm.0, json.bool(tem)) } bson.Binary(tem) -> { case tem { bson.MD5(bin) -> #(itm.0, json.string(md5.to_string(bin))) bson.UUID(bin) -> #(itm.0, json.string(uuid.to_string(bin))) //bson.Generic(bin) -> #(itm.0, json.string(generic.to_string(bin))) _ -> #(itm.0, json.string("")) } } bson.ObjectId(item) -> { #(itm.0, json.string(object_id.to_string(item))) } bson.Regex(tem) -> { #(itm.0, json.string(tem.0)) } bson.Document(lst) -> { #( itm.0, json.object( lst |> list.map(fn(op) { #(op.0, doc_to_json(op.1)) }), ), ) } bson.Array(item) -> { #(itm.0, json.array(item, of: fn(a: Value) { doc_to_json(a) })) } _ -> { #(itm.0, json.object([])) } } }) } _ -> list.new() } |> json.object } pub fn json_to_struct( myjson: json.Json, functor: fn(fn(String, Dynamic) -> Dynamic) -> a, ) { myjson |> json.to_string |> json.decode(fn(dyn) { Ok(dyn) }) |> result.map(fn(key) { let getter = fn(title: String, from: Dynamic) { key |> dynamic.field(named: title, of: fn(value) { Ok(value) }) |> result.unwrap(from) } Ok(functor(getter)) }) }