Typescript에서 JSON 문자열을 구문 분석하는 방법


108

Typescript에서 문자열을 JSON으로 구문 분석하는 방법이 있습니까?
예 : JS에서는 JSON.parse(). Typescript에 비슷한 기능이 있습니까?

다음과 같이 JSON 개체 문자열이 있습니다.

{"name": "Bob", "error": false}

1
홈페이지에 "TypeScript는 일반 자바 스크립트로 컴파일되는 자바 스크립트의 유형화 된 수퍼 세트"라고 나와 있습니다. JSON.parse () 함수는 평소처럼 사용할 수 있어야합니다.
sigalor jul.

1
Atom 텍스트 편집기를 사용 중이고 JSON.parse를 수행 할 때 오류가 발생합니다. '{}'유형의 인수는 '문자열'유형의 매개 변수에 할당 할 수 없습니다
ssd20072

22
이것은 매우 기본적인 질문이며 일부에게는 사소한 것처럼 보일 수 있지만 유효한 질문은 적지 않으며 SO에서 동등한 질문을 찾을 수 없으므로 질문을 유지하지 않을 실제 이유가 없습니다. 내 의견으로는 아래로 투표해서는 안됩니다.
Nitzan Tomer

2
@SanketDeshpande 사용할 때 JSON.parse결과가 아닌 객체를 얻습니다 string(자세한 내용은 내 대답 참조). 객체를 문자열로 바꾸려면 JSON.stringify대신 사용해야 합니다.
Nitzan Tomer

2
사실 이것은 두 가지 이유로 간단한 질문이 아닙니다. 첫째, JSON.parse ()는 동일한 종류의 객체를 반환하지 않습니다. 일부 인터페이스와 일치하지만 접근 자와 같은 지능적인 것은 존재하지 않습니다. 게다가, 우리는 사람들이 Google 물건을 검색 할 때가는 곳이되기를 원할까요?
speciesUnknown

답변:


176

Typescript는 자바 스크립트의 상위 집합이므로 자바 스크립트에서 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);

( 놀이터의 코드 )


9
입력이 유효한지 확인하는 방법 (유형 검사, typescript의 목적 중 하나)? 입력을 '{ "myString": "string", "myNumber": 4 }'로 대체 '{ "myString": "string", "myNumberBAD": 4 }'해도 실패하지 않으며 obj.myNumber는 undefined를 반환합니다.
David Portabella

3
@DavidPortabella 문자열의 내용에 대한 유형 검사를 할 수 없습니다. 그것은 런타임 문제, 그리고 유형 검사는 컴파일 시간입니다
Nitzan 토 메르

2
확인. typescript obj가 런타임에 인터페이스를 충족하는지 어떻게 확인할 수 있습니까? 즉,이 예제에서는 myNumber가 정의되지 않았습니다. 예를 들어 Scala Play에서는 Json.parse(text).validate[MyObj]. playframework.com/documentation/2.6.x/ScalaJson typescript에서 어떻게 똑같이 할 수 있습니까 (아마도 그렇게 할 외부 라이브러리가 있습니까?)?
David Portabella

1
@DavidPortabella 런타임에 MyObj존재하지 않기 때문에 쉽게 할 방법 이 없습니다. SO 다른 스레드의 많은 예를 들어,이 주제에 대해이 있습니다 타이프 라이터와 런타임에 객체 구현하는 경우 인터페이스를 확인
Nitzan 토 메르

7
알았어 고마워. 매일 나는 scalajs 사용에 대해 더 확신합니다.
David Portabella

8

형식 안전 JSON.parse

JSON.parseTS는 JS 수퍼 세트이므로을 계속 사용할 수 있습니다 . 여전히 문제가 남아 있습니다. JSON.parsereturns any, 이는 유형 안전성을 약화시킵니다. 더 강력한 유형에 대한 두 가지 옵션은 다음과 같습니다.

1. 사용자 정의 유형 가드 ( 놀이터 )

사용자 지정 유형 가드 는 가장 간단한 솔루션이며 종종 외부 데이터 유효성 검사에 충분합니다.

// 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빠른 실패 또는 try / catch JSON.parse오류 로 확장 될 수 있습니다 .

2. 외부 라이브러리

다양한 값의 유효성을 검사해야하는 경우 유형 보호 함수를 수동으로 작성하는 것이 번거 롭습니다. 이 작업을 지원하는 라이브러리가 있습니다-예 (전체 목록 없음) :

  • io-ts: rel. 인기 (현재 32,000 개 별), fp-ts피어 종속성, 함수형 프로그래밍 스타일
  • zod: 아주 새로운 (REPO : 2020년 3월 7일)는 최선의 노력을 기울이고 있습니다 더있을 수 있습니다 절차 / 객체 지향 보다io-ts
  • typescript-is: 컴파일러 API 용 TS 변환기, ttypescript 와 같은 추가 래퍼 필요
  • typescript-json-schema/ ajv: 유형에서 JSON 스키마를 생성하고ajv

더 많은 정보


4

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부터, 입력됩니다 StringBoolean그들이 입력을하고 형식화 된 출력을 반환 의미에서 모두 "트랜스 포머"입니다.

또한, value의지가 실제로 할 유형. 즉, name실제로 123이면 "123"유효한 문자열을 갖도록 로 변환됩니다 . 이는 String임의의 입력을 받아들이고를 반환하는 내장 함수 인 런타임에 사용했기 때문 string입니다.

여기서 작동하는 것을 볼 수 있습니다 . 자신을 설득하기 위해 다음을 시도하십시오.

  • const value정의 위로 마우스를 가져 가서 팝업에 올바른 유형이 표시되는지 확인합니다.
  • 변화 시도 "Bob"123샘플을 다시 실행합니다. 콘솔에서 이름이 문자열로 올바르게 변환되었음을 확인할 수 "123"있습니다.

" name실제로 123이면으로 변환됩니다 "123". 이것은 잘못된 것 같습니다. 모든 코드를 정확히 복사하여 붙여넣고 변경하면 value다시 돌아 {name: 123..오지 않습니다 {name:"123"...
Joncom

이상합니다. 여기에서 시도해보세요 : typescriptlang.org/play/index.html ( 123대신 사용 "Bob").
chowey

Transformed유형 을 정의 할 필요가 없다고 생각합니다 . 그냥 사용할 수 있습니다 Object. type Descriptor<T extends Object> = { ... };
lovasoa

감사합니다 @lovasoa, 당신이 맞습니다. Transformed유형은 완전히 불필요합니다. 그에 따라 답변을 업데이트했습니다.
chowey

실제로 JSON 객체에 올바른 유형이 있는지 확인하려면 JSON 객체 의 숫자이므로 자동으로 string으로 변환되는 것을 원하지 않습니다 . 123"123"
xuiqzy

1

Sparkson 과 같이 json의 유형 유효성 검사를 수행하는 라이브러리를 추가로 사용할 수 있습니다 . 응답을 구문 분석하려는 TypeScript 클래스를 정의 할 수 있습니다.

import { Field } from "sparkson";
class Response {
   constructor(
      @Field("name") public name: string,
      @Field("error") public error: boolean
   ) {}
}

라이브러리는 필수 필드가 JSON 페이로드에 있고 해당 유형이 올바른지 확인합니다. 또한 많은 유효성 검사 및 변환을 수행 할 수 있습니다.


1
당신이 위 도서관의 주요 기여자임을 언급해야합니다.
ford04

1

이를위한 훌륭한 라이브러리가 있습니다. 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의 유효성을 검사합니다.


0

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, }
);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.