I can extract a value from a json string in an Option with this code:
Code that works
import { identity, pipe } from "fp-ts/lib/function";
import * as E from "fp-ts/Either";
import * as O from "fp-ts/lib/Option";
import * as R from "fp-ts/lib/Record";
const jsonString = '{"a": 1}';
const a = pipe(
jsonString,
(x) =>
E.tryCatch(
() => JSON.parse(x),
(reason) => new Error(String(reason))
),
O.fromEither,
O.chain(R.lookup("a"))
);
console.log(a);
The type coming out of the E.tryCatch
call is Either<Error, any>
and R.lookup
seems to accept any
.
Code that doesn't work
Instead of using JSON.parse
directly, I would like to use parse
from the Json
module in fp-ts
.
import { identity, pipe } from "fp-ts/lib/function";
import * as J from "fp-ts/lib/Json";
import * as O from "fp-ts/lib/Option";
import * as R from "fp-ts/lib/Record";
const jsonString = '{"a": 1}';
const a = pipe(
jsonString,
J.parse,
O.fromEither,
O.chain(R.lookup("a")) <-- Error
);
Trying to use =R.lookup= on =Json= gives the following error:
Argument of type '<A>(r: Record<string, A>) => Option<A>'
is not assignable to parameter of type '(a: Json) => Option<Json>'
I guess it is because Json
can have lots of values (boolean | number | string | null | JsonArray | JsonRecord
) and only JsonRecord
would be compatible with Record
.
Question
How can I convert Json
to Record
(or anything letting me "lookup" value for key)? Or perhaps narrow my Json
object to JsonRecord
?
What I tried
Following the zipObject
example for fromFoldableMap
, I tried to do something like below without success:
import { identity, pipe } from "fp-ts/lib/function";
import * as J from "fp-ts/lib/Json";
import * as O from "fp-ts/lib/Option";
import * as R from "fp-ts/lib/Record";
const jsonString = '{"a": 1}';
const a = pipe(
jsonString,
J.parse,
O.fromEither,
O.map((kvs) => R.fromFoldableMap(last<J.Json>(), R.Foldable)(kvs, identity)), <-- Not working
O.chain(R.lookup("a"))
);