でJSONをデコード


タイプスクリプトはJavaScriptプログラムにタイプセーフを追加するのに非常によく適していますが、それ自身では、実行時にクラッシュしないことを保証するのに十分ではありません.
この記事はJSON decoders 実行時環境にTypeScriptコンパイル時の保証を拡張するのに役立ちます.

ランタイム対コンパイル時間


ユーザーとの取引に取り組んでいるので、アプリケーションを作成するUser 種類:
interface User {
   firstName: string;
   lastName: string;
   picture: string;
   email: string;
}
このタイプを使用して、注釈を付ける/me APIのエンドポイントの結果、そしてあなたはこれですべての種類を行いますUser しかし、アプリケーションのプロファイル領域に集中しよう
  • の連結を表示しますfirstName + lastName .
  • 下にfirstName + lastName また、email .
  • 最後に、あなたはpicture ユーザーの、または存在しない場合は、デフォルトのイメージ.
  • 何が間違って行くことができる?さて、始めにUser タイプは真実を言っていない、それはすべての置換を表現しないUser APIが返す図形.
    いくつかの例を見てみましょう.
    // The result has null properties
    { firstName: "John", lastName: null, picture: null, email: "[email protected]" }
    
    // The API returned null
    null
    
    // The result has undefined properties
    { firstName: "John", lastName: "Doe", email: "[email protected]" }
    
    // The API contract changed and the UI team wasn't notified
    { fName: "John", lName: "Doe", picture: 'pic.jpg', email: "[email protected]" }
    

    これらの問題に対処することができます防御プログラミング技術、A . K .null / undefined チェックif しかし、他の誰かが使用したいときに何が起こるか/me どこかほかの結果?たぶんあなたの同僚はUser タイプ、なぜ?何が起こるかランタイムエラーの新しいベクトルを導入した.

    JSONデコーダを入力します


    JSONデコーダを使用して、指定したランタイム値が特定のコンパイル時型に準拠していることを確認します.
    JSONのデコーダは最近のおかげで人気を得ているElm .
    エルムのJSONデコーダは、言語のコア部分であり、彼らはelm通信にスムーズなJSを確保するためにすべての場所で使用されます.
    JSONデコーダの背後にあるアイデアは、基本的なデコーダのコレクションを持っていることですstring , number , boolean , object , array ... ) あなたがより複雑なデコーダに作成することができます.

    最新のJSONデコーダライブラリ


    そこにはいくつかのJSONデコードライブラリがありますが、しばらく前から研究を行ったとき、残りから出てきたものがあります.Daniel Van Den Eijkel Elmのデコードライブラリの原則を維持するものを作成しました.
    残念ながら、図書館は未完成で未発表だったので、私はそれをフォークして、それを磨いて、名前の下でNPMパッケージとしてそれをリリースすることに決めましたts.data.json .
    ライブラリへの私の貢献は、ドキュメント、良いエラー報告、ユニットテスト、APIの改善、いくつかの新しいデコーダとNPMパッケージを公開している.

    JSONデコーダの使用


    ライブラリをインストールします
    npm install ts.data.json --save
    

    デコード基本


    我々の習慣を実行する前にUser デコードしてみましょうstring 最初から最後まで.
    import { JsonDecoder } from 'ts.data.json';
    
    console.log( JsonDecoder.string.decode('Hi!') ); // Ok({value: 'Hi!'})
    
    終わり!🎉

    アンラッピングデコーダ結果


    前の例で見たように、デコード処理には2つのステップがあります.
  • まず、デコーダを宣言しますJsonDecoder.string .
  • 第二に、JavaScriptの値を*.decode('Hi!') , を返します.Ok .
  • なぜ結果を包んでいるのかOk インスタンス?失敗した場合には結果をErr インスタンス.
    見てみましょうdecode() 署名は以下のようになります:
    decode(json: any): Result<a>
    
    Result<a> ユニオンタイプOk and Err .
    type Result<a> = Ok<a> | Err;
    
    だからほとんどの時間我々は使用されませんdecode() , 代わりに我々はおそらく使用するでしょうdecodePromise() .
    見てみましょうdecodePromise() 署名は以下のようになります:
    decodePromise<b>(json: any): Promise<a>
    
    デコードしてみましょうstring 始めから終わりまでdecodePromise() :
    import { JsonDecoder } from 'ts.data.json';
    
    const json = Math.random() > 0.5 ? 'Hi!' : null;
    JsonDecoder.string.decodePromise(json)
      .then(value => {
        console.log(value);
      })
      .catch(error => {
        console.log(error);
      });
    
    時間の半分は、我々はthen() ルートと取得Hi! , そして、半分の時間我々はcatch() ルートゲットnull is not a valid string .
    我々が基本を知っている今、真剣になって、我々の習慣を構築しましょうUser デコーダ.

    ユーザデコーダ


    原始的なデコーダは別として:
  • JsonDecoder.string: Decoder<string>
  • JsonDecoder.number: Decoder<number>
  • JsonDecoder.boolean: Decoder<boolean>
  • 他のより複雑なデコーダもありますUser 私たちはJsonDecoder.object デコーダ
  • JsonDecoder.object<a>(decoders: DecoderObject<a>, decoderName: string): Decoder<a>
  • すべてのデコーダが戻っているそのデコーダ< A >は何ですか?

    Decoders have the logic to decode a particular value, but they don't know how to execute it, this is what the Decoder class is for.
    Decoder<a> has methods to execute, unwrap, chain and transform decoders / decoder values.


    デコードしてみましょうUser 最初から最後まで我々はこれまで学んだすべてのトリックを使用して
    import { JsonDecoder } from 'ts.data.json';
    
    interface User {
      firstName: string;
      lastName: string;
    }
    
    const userDecoder = JsonDecoder.object<User>(
      {
        firstName: JsonDecoder.string,
        lastName: JsonDecoder.string
      },
      'User'
    );
    
    const validUser = {
      firstName: 'Nils',
      lastName: 'Frahm'
    };
    
    const invalidUser = {
      firstName: null,
      lastName: 'Wagner'
    };
    
    const json = Math.random() > 0.5 ? validUser : invalidUser;
    
    userDecoder
      .decodePromise(json)
      .then(value => {
        console.log(value);
      })
      .catch(error => {
        console.log(error);
      });
    
    我々が得る時間の半分{firstName: "Nils", lastName: "Frahm"} そして、我々が得る時間の半分<User> decoder failed at key "firstName" with error: null is not a valid string . JsonDecoder 私たちは覆われている.

    ウサギ穴を行く


    私たちは、このライブラリが可能であるものの表面をひっかき始めました.デコードできます:
  • アレイ
  • 辞書
  • 再帰的データ構造
  • NULL
  • 未定義
  • そして、他の空想的なもの.
    に移動GitHub repo と見つける!