Typescriptで文字列をJSONとして解析する方法はありますか?
例:JSでは、を使用できますJSON.parse()
。Typescriptに同様の関数はありますか?
次のようなJSONオブジェクト文字列があります。
{"name": "Bob", "error": false}
Typescriptで文字列をJSONとして解析する方法はありますか?
例:JSでは、を使用できますJSON.parse()
。Typescriptに同様の関数はありますか?
次のようなJSONオブジェクト文字列があります。
{"name": "Bob", "error": false}
JSON.parse
すると、結果としてオブジェクトではなくオブジェクトが取得されますstring
(詳細については、私の回答を参照してください)。オブジェクトを文字列に変換したい場合は、JSON.stringify
代わりに使用する必要があります。
回答:
Typescriptはjavascript(のスーパーセット)なので、javascriptと同じように使用JSON.parse
できます。
let obj = JSON.parse(jsonString);
typescriptでのみ、結果のオブジェクトに型を持つことができます。
interface MyObj {
myString: string;
myNumber: number;
}
let obj: MyObj = JSON.parse('{ "myString": "string", "myNumber": 4 }');
console.log(obj.myString);
console.log(obj.myNumber);
(遊び場のコード)
'{ "myString": "string", "myNumber": 4 }'
ことにより、'{ "myString": "string", "myNumberBAD": 4 }'
失敗することはありません、とobj.myNumberは未定義を返します。
Json.parse(text).validate[MyObj]
。playframework.com/documentation/2.6.x/ScalaJson typescriptで同じようにするにはどうすればよいですか(そうするための外部ライブラリがあるのでしょうか?)?
MyObj
は存在しないため、簡単にはできません。たとえば、この件に関しては、SOには他にもたくさんのスレッドがあります。たとえば、オブジェクトが実行時にTypeScriptを使用してインターフェイスを実装しているかどうかを確認します
JSON.parse
JSON.parse
TSはJSスーパーセットであるため、引き続き使用できます。まだ問題がありJSON.parse
ますany
。タイプセーフティを損なうreturnです。より強力なタイプの2つのオプションを次に示します。
カスタムタイプガードは最も単純なソリューションであり、多くの場合、外部データの検証には十分です。
// For example, you expect to parse a given value with `MyType` shape
type MyType = { name: string; description: string; }
// Validate this value with a custom type guard
function isMyType(o: any): o is MyType {
return "name" in o && "description" in o
}
JSON.parse
ラッパーは、入力としてタイプガードを取り、解析され、入力した値を返すことができます。
const safeJsonParse = <T>(guard: (o: any) => o is T) => (text: string): ParseResult<T> => {
const parsed = JSON.parse(text)
return guard(parsed) ? { parsed, hasError: false } : { hasError: true }
}
type ParseResult<T> =
| { parsed: T; hasError: false; error?: undefined }
| { parsed?: undefined; hasError: true; error?: unknown }
使用例:
const json = '{ "name": "Foo", "description": "Bar" }';
const result = safeJsonParse(isMyType)(json) // result: ParseResult<MyType>
if (result.hasError) {
console.log("error :/") // further error handling here
} else {
console.log(result.parsed.description) // result.parsed now has type `MyType`
}
safeJsonParse
高速に失敗するか、JSON.parse
エラーを試行/キャッチするように拡張される場合があります。
多くの異なる値を検証する必要がある場合、タイプガード関数を手動で記述するのは面倒になります。このタスクを支援するライブラリがあります-例(包括的なリストはありません):
io-ts
:rel。ポピュラー(現在は3.2kスター)、fp-ts
ピア依存、関数型プログラミングスタイルzod
:(レポ:2020年3月7日)は非常に新しい、努力するが、より可能にする手続き/オブジェクト指向よりio-ts
typescript-is
:コンパイラAPIのTSトランスフォーマー、ttypescriptのような追加のラッパーが必要typescript-json-schema
/ ajv
:タイプからJSONスキーマを作成し、それを使用して検証しますajv
JSONに検証済みのTypescriptタイプを持たせたい場合は、その検証作業を自分で行う必要があります。これは新しいことではありません。単純なJavascriptでは、同じことをする必要があります。
検証ロジックを「変換」のセットとして表現したい。私Descriptor
は変換のマップとして定義します:
type Descriptor<T> = {
[P in keyof T]: (v: any) => T[P];
};
次に、これらの変換を任意の入力に適用する関数を作成できます。
function pick<T>(v: any, d: Descriptor<T>): T {
const ret: any = {};
for (let key in d) {
try {
const val = d[key](v[key]);
if (typeof val !== "undefined") {
ret[key] = val;
}
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
throw new Error(`could not pick ${key}: ${msg}`);
}
}
return ret;
}
これで、JSON入力を検証するだけでなく、Typescriptタイプを構築しています。上記のジェネリック型は、結果が「変換」から型を推測することを保証します。
変換がエラーをスローする場合(検証を実装する方法です)、エラーの原因となったキーを示す別のエラーでラップします。
あなたの例では、私はこれを次のように使用します:
const value = pick(JSON.parse('{"name": "Bob", "error": false}'), {
name: String,
error: Boolean,
});
今value
以来、型付けされますString
とBoolean
、彼らは入力を取り、型指定された出力を返すという意味で、両方の「変圧器」です。
さらに、value
意志は実際にもそのタイプ。つまり、name
実際123
に"123"
だった場合、有効な文字列が得られるように変換されます。これはString
、実行時に任意の入力を受け入れてを返す組み込み関数を使用したためstring
です。
ここでこれが機能しているのを見ることができます。次のことを試して、納得してください。
const value
定義にカーソルを合わせると、ポップオーバーに正しいタイプが表示されます。"Bob"
し123
て再実行してみてください。コンソールで、名前が文字列に正しく変換されていることがわかります"123"
。name
実際にして123
、それはに変換されます"123"
。これは正しくないように思わ私は。。value
戻って来ている{name: 123..
ではない{name:"123"..
、私は正確にすべてのコードを貼り付けて、その変更を行うコピーするとき。
Transformed
タイプを定義する必要はないと思います。そのまま使えますObject
。type Descriptor<T extends Object> = { ... };
Transformed
タイプは全く不要です。それに応じて答えを更新しました。
さらに、Sparksonなど、jsonの型検証を実行するライブラリを使用できます。それらはあなたがあなたの応答を解析したいTypeScriptクラスを定義することを可能にします。
import { Field } from "sparkson";
class Response {
constructor(
@Field("name") public name: string,
@Field("error") public error: boolean
) {}
}
ライブラリーは、必須フィールドがJSONペイロードに存在するかどうか、およびそれらのタイプが正しいかどうかを検証します。また、一連の検証と変換を行うこともできます。
それのための素晴らしいライブラリがありますts-json-object
あなたの場合、次のコードを実行する必要があります:
import {JSONObject, required} from 'ts-json-object'
class Response extends JSONObject {
@required
name: string;
@required
error: boolean;
}
let resp = new Response({"name": "Bob", "error": false});
このライブラリは、解析する前にjsonを検証します
JSON.parse
TypeScriptで利用できるので、そのまま使用できます。
JSON.parse('{"name": "Bob", "error": false}') // Returns a value of type 'any'
ただし、多くの場合、typeの値を処理するのではなく、特定の型と一致することを確認しながら、JSONオブジェクトを解析する必要がありますany
。その場合、次のような関数を定義できます。
function parse_json<TargetType extends Object>(
json: string,
type_definitions: { [Key in keyof TargetType]: (raw_value: any) => TargetType[Key] }
): TargetType {
const raw = JSON.parse(json);
const result: any = {};
for (const key in type_definitions) result[key] = type_definitions[key](raw[key]);
return result;
}
この関数は、JSON文字列と、作成するオブジェクトの各フィールドをロードする個々の関数を含むオブジェクトを受け取ります。次のように使用できます。
const value = parse_json(
'{"name": "Bob", "error": false}',
{ name: String, error: Boolean, }
);