TypeScript 杂记七 《JSON Parser》
Posted 左手121
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript 杂记七 《JSON Parser》相关的知识,希望对你有一定的参考价值。
TypeScript 杂记七 《JSON Parser》
思路
- 先写主类型的大概
- 如果是 包裹则返回 ParserObject
- 如果是 [] 包裹则返回 ParserArray
- 否则返回原本的数据,这里我们额外处理一下 true,false,null
- 不考虑 Numbers 和 Unicode
type Parser<T extends string> = T extends `$infer S`
? ParserObject<S>
: T extends `[$infer S]`
? ParserArray<S>
: T extends "true"
? true
: T extends "false"
? false
: T extends "null"
? null
: // Numbers and Unicode escape (\\uxxxx) in JSON can be ignored. You needn't to parse them.
T;
- 考虑到下边几种情况,因此我们要先处理一下数据
" "a":1 "
处理前后空格"aaa"
返回的是"\\"aaa\\""
,因此需要处理一下前后的引号
type TrimBase<
T extends string,
R extends string = " "
> = T extends `$R$infer S`
? TrimBase<S, R>
: T extends `$infer S$R`
? TrimBase<S, R>
: T;
// 处理空格->处理引号
type Trim<T extends string> = TrimBase<TrimBase<T>, '"'>;
type ParserHelper<T extends string> = T extends `$infer S`
? ParserObject<Trim<S>> // 特殊解决一下 这种情况
: T extends `[$infer S]`
? ParserArray<S>
: T extends "true"
? true
: T extends "false"
? false
: T extends "null"
? null
: // Numbers and Unicode escape (\\uxxxx) in JSON can be ignored. You needn't to parse them.
T;
type Parser<T extends string> = ParserHelper<Trim<T>>;
-
采用递归的形式
- 先解析出最一层的数据,拿到 key 和 value
- value 则再次调用 Parser
- 重复第一步
-
ParserArray
的实现- 传入的数据不带去掉最外层的 []
- 理论上对于一个普通数字,遇到
,
则前边的内容的表示是一项 - 但是因为有可能是一个对象或者数组我们需要额外处理一下
- V 用来临时存储数据
- L 用来存储遇到的 [ 个数
- 如果遇到 [ 或者 则 L 数组加一
- 如果遇到 ] 或者 则 L 数组减一
- 如果遇到 , 且 L 数组为空,则表示一项完成了,把 V 存到 R 里边,继续下一项
- 否则就把对应的字符加入到 V 中
- 注意:存入的 V 值,需要递归去调用
Parser
type ParserArray<
T extends string,
R extends string[] = [],
V extends string = "",
L extends unknown[] = []
> = T extends `$infer S$infer E`
? S extends ","
? L extends []
? ParserArray<E, [...R, Parser<V>], "", L>
: ParserArray<E, R, `$V$S`, L>
: S extends "[" | ""
? ParserArray<E, R, `$V$S`, [...L, unknown]>
: S extends "" | "]"
? L extends [unknown, ...infer B]
? ParserArray<E, R, `$V$S`, B>
: ParserArray<E, R, `$V$S`, L>
: ParserArray<E, R, `$V$S`, L>
: [...R, Parser<V>];
ParserObject
的实现- 不同的是我们需要两个参数,用来存储 K 和 V
- L=false 获取 K,只要遇到 : 就停止前边的内容就是对应的 key
- L=true 获取值,这里的逻辑就和数组是一样的,不同的是这里只求一项
- 求出 value 的时候,我们把 K 和 V 存到 R 中,重新开始下一项
type ParserObject<
T extends string,
R extends Record<string, any> = ,
K extends string = "",
V extends string = "",
F extends boolean = false,
L extends unknown[] = []
> = T extends `$infer S$infer E`
? F extends false
? S extends ":"
? ParserObject<E, R, Trim<K>, V, true, L>
: ParserObject<E, R, `$K$S`, V, F, L>
: S extends ","
? L extends []
? ParserObject<
E,
[P in keyof R]: R[P] & [P in K]: Parser<V> ,
"",
"",
false,
L
>
: ParserObject<E, R, K, `$V$S`, F, L>
: S extends "[" | ""
? ParserObject<E, R, K, `$V$S`, F, [...L, unknown]>
: S extends "]" | ""
? L extends [unknown, ...infer B]
? ParserObject<E, R, K, `$V$S`, F, B>
: ParserObject<E, R, K, `$V$S`, F, L>
: ParserObject<E, R, K, `$V$S`, F, L>
: K extends ""
? [P in keyof R]: R[P]
: ParserObject<
"",
[P in keyof R]: R[P] & [P in K]: Parser<V> ,
"",
"",
false,
L
>;
完整示例
type TrimBase<
T extends string,
R extends string = " "
> = T extends `$R$infer S`
? TrimBase<S, R>
: T extends `$infer S$R`
? TrimBase<S, R>
: T;
type Trim<T extends string> = TrimBase<TrimBase<T>, '"'>;
type ParserObject<
T extends string,
R extends Record<string, any> = ,
K extends string = "",
V extends string = "",
F extends boolean = false,
L extends unknown[] = []
> = T extends `$infer S$infer E`
? F extends false
? S extends ":"
? ParserObject<E, R, Trim<K>, V, true, L>
: ParserObject<E, R, `$K$S`, V, F, L>
: S extends ","
? L extends []
? ParserObject<
E,
[P in keyof R]: R[P] & [P in K]: Parser<V> ,
"",
"",
false,
L
>
: ParserObject<E, R, K, `$V$S`, F, L>
: S extends "[" | ""
? ParserObject<E, R, K, `$V$S`, F, [...L, unknown]>
: S extends "]" | ""
? L extends [unknown, ...infer B]
? ParserObject<E, R, K, `$V$S`, F, B>
: ParserObject<E, R, K, `$V$S`, F, L>
: ParserObject<E, R, K, `$V$S`, F, L>
: K extends ""
? [P in keyof R]: R[P]
: ParserObject<
"",
[P in keyof R]: R[P] & [P in K]: Parser<V> ,
"",
"",
false,
L
>;
type ParserArray<
T extends string,
R extends string[] = [],
V extends string = "",
L extends unknown[] = []
> = T extends `$infer S$infer E`
? S extends ","
? L extends []
? ParserArray<E, [...R, Parser<V>], "", L>
: ParserArray<E, R, `$V$S`, L>
: S extends "[" | ""
? ParserArray<E, R, `$V$S`, [...L, unknown]>
: S extends "" | "]"
? L extends [unknown, ...infer B]
? ParserArray<E, R, `$V$S`, B>
: ParserArray<E, R, `$V$S`, L>
: ParserArray<E, R, `$V$S`, LTypeScript 杂记七 《JSON Parser》
TypeScript 杂记九 《Integers Comparator》
TypeScript 杂记九 《Integers Comparator》