如何使用 io-ts 解析和验证 JsonRecord?
How to parse and validate a JsonRecord with io-ts?
我需要解析包含 json 的字符串。我需要确保输出是 JsonRecord
而不是 json 原语。
我已经尝试使用 fp-ts
和 io-ts
来解决这个问题。到目前为止,我知道 t.UnknownRecord.decode
将 return 和 Either
。对于原语,这将是 left
,对于记录,这将是 right
。我不确定如何将它与 parseJSON
一起组合。当我尝试时出现类型错误。请参阅下面的测试之间的评论。
import { pipe } from "fp-ts/lib/function";
import * as E from "fp-ts/lib/Either";
import * as t from "io-ts";
const onLeft = () => "NO";
const onRight = () => "YES";
describe("parsing strings of json", () => {
it("should return a right for a json record", () => {
const record: E.JsonRecord = { banana: "yellow fruit" };
expect(t.UnknownRecord.decode(record)).toEqual(E.right(record));
});
it("should not return a right for a json primitive", () => {
const primitive: E.Json = "banana is a yellow fruit";
expect(t.UnknownRecord.decode(primitive)).not.toEqual(
E.right(primitive)
);
});
it("should say YES for a string containing a json record", () => {
expect(
pipe(
E.parseJSON('{"banana":"yellow fruit"}', E.toError),
E.chain(t.UnknownRecord.decode),
E.fold(onLeft, onRight)
)
).toEqual("YES");
});
// Argument of type 'Either<Error, Json>' is not assignable to parameter of type 'Either<Errors, unknown>'.
// Type 'Left<Error>' is not assignable to type 'Either<Errors, unknown>'.
// Type 'Left<Error>' is not assignable to type 'Left<Errors>'.
// Type 'Error' is missing the following properties from type 'Errors': length, pop, push, concat, and 28 more.
it("should say NO for a string containing a json primitive", () => {
expect(
pipe(
E.parseJSON('"banana is a yellow fruit"', E.toError),
E.chain(t.UnknownRecord.decode),
E.fold(onLeft, onRight)
)
).toEqual("NO");
});
});
在这里尝试使用 chain
是正确的还是我应该使用其他东西?
在得到一些建议后,我现在知道答案如下:
import * as f from 'fp-ts/lib/function';
...
it('should say YES for a string containing a json record', () => {
expect(
f.pipe(
E.parseJSON('{"banana":"yellow fruit"}', E.toError),
E.chain(f.flow(t.UnknownRecord.decode, E.mapLeft(E.toError))),
E.fold(onLeft, onRight)
)
).toEqual('YES');
});
it('should say NO for a string containing a json primitive', () => {
expect(
f.pipe(
E.parseJSON('"banana is a yellow fruit"', E.toError),
E.chain(f.flow(t.UnknownRecord.decode, E.mapLeft(E.toError))),
E.fold(onLeft, onRight)
)
).toEqual('NO');
});
我需要解析包含 json 的字符串。我需要确保输出是 JsonRecord
而不是 json 原语。
我已经尝试使用 fp-ts
和 io-ts
来解决这个问题。到目前为止,我知道 t.UnknownRecord.decode
将 return 和 Either
。对于原语,这将是 left
,对于记录,这将是 right
。我不确定如何将它与 parseJSON
一起组合。当我尝试时出现类型错误。请参阅下面的测试之间的评论。
import { pipe } from "fp-ts/lib/function";
import * as E from "fp-ts/lib/Either";
import * as t from "io-ts";
const onLeft = () => "NO";
const onRight = () => "YES";
describe("parsing strings of json", () => {
it("should return a right for a json record", () => {
const record: E.JsonRecord = { banana: "yellow fruit" };
expect(t.UnknownRecord.decode(record)).toEqual(E.right(record));
});
it("should not return a right for a json primitive", () => {
const primitive: E.Json = "banana is a yellow fruit";
expect(t.UnknownRecord.decode(primitive)).not.toEqual(
E.right(primitive)
);
});
it("should say YES for a string containing a json record", () => {
expect(
pipe(
E.parseJSON('{"banana":"yellow fruit"}', E.toError),
E.chain(t.UnknownRecord.decode),
E.fold(onLeft, onRight)
)
).toEqual("YES");
});
// Argument of type 'Either<Error, Json>' is not assignable to parameter of type 'Either<Errors, unknown>'.
// Type 'Left<Error>' is not assignable to type 'Either<Errors, unknown>'.
// Type 'Left<Error>' is not assignable to type 'Left<Errors>'.
// Type 'Error' is missing the following properties from type 'Errors': length, pop, push, concat, and 28 more.
it("should say NO for a string containing a json primitive", () => {
expect(
pipe(
E.parseJSON('"banana is a yellow fruit"', E.toError),
E.chain(t.UnknownRecord.decode),
E.fold(onLeft, onRight)
)
).toEqual("NO");
});
});
在这里尝试使用 chain
是正确的还是我应该使用其他东西?
在得到一些建议后,我现在知道答案如下:
import * as f from 'fp-ts/lib/function';
...
it('should say YES for a string containing a json record', () => {
expect(
f.pipe(
E.parseJSON('{"banana":"yellow fruit"}', E.toError),
E.chain(f.flow(t.UnknownRecord.decode, E.mapLeft(E.toError))),
E.fold(onLeft, onRight)
)
).toEqual('YES');
});
it('should say NO for a string containing a json primitive', () => {
expect(
f.pipe(
E.parseJSON('"banana is a yellow fruit"', E.toError),
E.chain(f.flow(t.UnknownRecord.decode, E.mapLeft(E.toError))),
E.fold(onLeft, onRight)
)
).toEqual('NO');
});