टाइपस्क्रिप्ट में JSON के रूप में तार पार्स करने का एक तरीका है।
उदाहरण: JS में, हम उपयोग कर सकते हैं JSON.parse()। क्या टाइपस्क्रिप्ट में समान कार्य है?
मेरे पास JSON ऑब्जेक्ट स्ट्रिंग निम्नानुसार है:
{"name": "Bob", "error": false}
टाइपस्क्रिप्ट में JSON के रूप में तार पार्स करने का एक तरीका है।
उदाहरण: JS में, हम उपयोग कर सकते हैं JSON.parse()। क्या टाइपस्क्रिप्ट में समान कार्य है?
मेरे पास JSON ऑब्जेक्ट स्ट्रिंग निम्नानुसार है:
{"name": "Bob", "error": false}
JSON.parseतो आपको एक परिणाम के रूप में एक वस्तु मिलती है और एक नहीं string(अधिक के लिए मेरा उत्तर देखें)। यदि आप किसी ऑब्जेक्ट को स्ट्रिंग में बदलना चाहते हैं, तो आपको JSON.stringifyइसके बजाय उपयोग करने की आवश्यकता है ।
जवाबों:
टाइपस्क्रिप्ट जावास्क्रिप्ट का (एक सुपरसेट) है, इसलिए आप बस उसी तरह का उपयोग करते हैं JSON.parseजैसा आप जावास्क्रिप्ट में करते हैं:
let obj = JSON.parse(jsonString);
केवल उस टाइपस्क्रिप्ट में आप परिणामस्वरूप ऑब्जेक्ट के लिए एक प्रकार हो सकते हैं:
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 आप टाइपस्क्रिप्ट में समान कैसे कर सकते हैं (शायद ऐसा करने के लिए कोई बाहरी पुस्तकालय है?)।
MyObjमौजूद नहीं है। इस विषय के बारे में SO में बहुत सारे अन्य सूत्र हैं, उदाहरण के लिए: देखें कि क्या ऑब्जेक्ट टाइपस्क्रिप्ट के साथ रनटाइम पर एक इंटरफ़ेस लागू करता है
JSON.parseआप उपयोग करना जारी रख सकते हैं JSON.parse, क्योंकि TS एक JS सुपरसेट है। अभी भी एक समस्या बाकी है: JSON.parseरिटर्न any, जो प्रकार की सुरक्षा को कमजोर करता है। यहाँ मजबूत प्रकारों के लिए दो विकल्प दिए गए हैं:
कस्टम प्रकार गार्ड सबसे सरल समाधान हैं और बाहरी डेटा सत्यापन के लिए अक्सर पर्याप्त होते हैं:
// 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: जारी करें। लोकप्रिय (वर्तमान में 3.2k सितारे), fp-tsसहकर्मी निर्भरता, कार्यात्मक प्रोग्रामिंग शैलीzod: काफी नया (रेपो: 2020-03-07), इससे अधिक प्रक्रियात्मक / वस्तु-उन्मुख होने का प्रयास करता हैio-tstypescript-is: कंपाइलर एपीआई के लिए टीएस ट्रांसफॉर्मर, अतिरिक्त रैपर जैसे ttypescript की जरूरतtypescript-json-schema/ ajv: टाइप से JSON स्कीमा बनाएं और इसे मान्य करेंajvयदि आप चाहते हैं कि आपका JSON एक मान्य टाइपस्क्रिप्ट प्रकार का हो, तो आपको वह सत्यापन स्वयं करने की आवश्यकता होगी। यह कोई नई बात नहीं है। सादे जावास्क्रिप्ट में, आपको वही करने की आवश्यकता होगी।
मुझे "ट्रांसफ़ॉर्म" के सेट के रूप में अपना सत्यापन तर्क व्यक्त करना पसंद है। मैं 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 इनपुट को सत्यापित कर रहा हूं, बल्कि मैं टाइपस्क्रिप्ट टाइप भी बना रहा हूं। उपरोक्त सामान्य प्रकार यह सुनिश्चित करते हैं कि परिणाम आपके "रूपांतरों" से प्रकारों को संक्रमित करता है।
मामले में परिवर्तन एक त्रुटि फेंकता है (जो है कि आप सत्यापन कैसे लागू करेंगे), मैं इसे एक और त्रुटि के साथ लपेटना पसंद करता हूं जिसमें यह त्रुटि दिखाई देती है।
आपके उदाहरण में, मैं इसका उपयोग इस प्रकार करूंगा:
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"..है जब मैं अपने सभी कोड वास्तव में पेस्ट करें और यह बदलाव लाना कॉपी।
123इसके बजाय का उपयोग करके "Bob")।
Transformedप्रकार को परिभाषित करने की आवश्यकता है । आप बस इस्तेमाल कर सकते हैं Object। type Descriptor<T extends Object> = { ... };
Transformedप्रकार पूरी तरह अनावश्यक है। मैंने उसी हिसाब से जवाब अपडेट किया है।
123"123"
आप अतिरिक्त रूप से पुस्तकालयों का उपयोग कर सकते हैं जो स्पार्कसन जैसे आपके जोंस का प्रकार सत्यापन करते हैं । वे आपको टाइपस्क्रिप्ट क्लास को परिभाषित करने की अनुमति देते हैं, जिसमें आप अपनी प्रतिक्रिया को पार्स करना चाहते हैं, आपके मामले में यह हो सकता है:
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.parse टाइपस्क्रिप्ट में उपलब्ध है, इसलिए आप इसका उपयोग कर सकते हैं:
JSON.parse('{"name": "Bob", "error": false}') // Returns a value of type 'any'
हालाँकि, आप अक्सर एक 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, }
);