TypeScript 杂记七 《JSON Parser》

Posted 左手121

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript 杂记七 《JSON Parser》相关的知识,希望对你有一定的参考价值。

TypeScript 杂记七 《JSON Parser》

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 杂记十二 《Multiply》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记九 《Integers Comparator》

TypeScript 杂记一