将 json 解析为 typescript 中的接口并检查是不是正常
Posted
技术标签:
【中文标题】将 json 解析为 typescript 中的接口并检查是不是正常【英文标题】:Parsing json to interface in typescript and check if it is ok将 json 解析为 typescript 中的接口并检查是否正常 【发布时间】:2020-12-17 02:53:33 【问题描述】:如何将 Json 字符串解析为嵌套接口类型?并检查是否正常?
我有一个例子,但我的模型更复杂:
export interface User =
name: Field;
surname: Field;
;
export interface Field = icon: string; text: string; visibility: boolean ;
export interface Users = User[]
应该是:
export type user =
name: field;
surname: field;
;
export type field = icon: string; text: string; visibility: boolean ;
export type users = user[]
或者它会是类。没关系。
这里是一个 json 示例:
[
"name": "text": "David", "icon": "icon1.png", "visibility": true ,
"surname": "text": "Smith", "icon": "icon2.png", "visibility": true
,
"name": "text": "Arthur", "icon": "icon3.png", "visibility": true ,
"surname": "text": "L.", "icon": "icon6.png", "visibility": true
,
"name": "text": "Anthony", "icon": "icon1.png", "visibility": false ,
"surname": "text": "Isaacson", "icon": "icon2.png", "visibility": true
,
"name": "text": "Mike", "icon": "icon3.png", "visibility": true ,
"surname": "text": "Jobs", "icon": "icon5.png", "visibility": false
]
编辑:
这里是 Chithambara 方法无效的示例:Playground
【问题讨论】:
【参考方案1】:如果您的验证需求足够复杂,我会评估io-ts 之类的使用情况。它是一个用于根据代码中的元数据自动生成运行时验证的库。
如果您的需求比较有限,您可以利用UserDefined Type Guards。
类型保护的作用是获取unknown
(或any
,这种函数内部确实没有区别)并告诉编译器传入的对象兼容某个界面。
export interface Field
icon: string;
text: string;
visibility: boolean;
export interface User
name: Field;
surname: Field;
function isField(obj: any): obj is Field
return (
obj != null &&
typeof obj.icon === "string" &&
typeof obj.text === "string" &&
typeof obj.visibility === "boolean"
);
function isUser(obj: any): obj is User
return obj != null && isField(obj.name) && isField(obj.surname);
// you can get fancy and write something like
// return obj != null && ['name', 'surname'].every(fieldName => isField(obj[fieldName]))
// alternative isUser implementation, using a
// prototype. This will give you a compile error is the
// interface is updated, but not this prototype.
const userProto: User =
name: null,
surname: null
;
function isUserDynamic(obj: any): obj is User
return obj != null && Object.keys(userProto).every(fieldName => isField(obj[fieldName]));
function validateUserArray(obj: any): obj is User[]
if (obj == null)
// depending upon the desired approach, you can throw an exception and bail out,
// or simply return false.
throw new Error("The array cannot be null");
if (!Array.isArray(obj)) return false;
obj.forEach((user, i) =>
if (!isUser(user))
throw new Error(
`Error at index $i: $JSON.stringify(user) is not a valid user.`
);
);
return true;
const json = `[
"name": "text": "David", "icon": "icon1.png", "visibility": true ,
"surname": "text": "Smith", "icon": "icon2.png", "visibility": true
,
"name": "text": "Arthur", "icon": "icon3.png", "visibility": true ,
"surname": "text": "L.", "icon": "icon6.png", "visibility": true
,
"name": "text": "Anthony", "icon": "icon1.png", "visibility": false ,
"surname": "text": "Isaacson", "icon": "icon2.png", "visibility": true
,
"name": "text": "Mike", "icon": "icon3.png", "visibility": true ,
"surname": "text": "Jobs", "icon": "icon5.png", "visibility": false
]`;
const deserialized: any = JSON.parse(json);
let validatedArray: User[];
if (validateUserArray(deserialized))
// here deserialized is a User[], not an any.
validatedArray = deserialized;
【讨论】:
看起来可以,但是代码维护起来很复杂,有没有其他更易维护的方法? 如果您的类型是“常规的”(即用户界面有 20 个字段,所有字段类型均为 Field),您可以将 User 设为类,使用const proto = new User()
实例化原型并使用 Object。 keys(proto) 通过 isUser 中的return obj != null && Object.keys(proto).every(fieldName => isField(obj[fieldName]))
获取要检查的字段列表。
或者,使用io-ts
。当然,更易于维护,但可能不是那么简单。您还可以构建一个代码生成器,为您构建isUser
函数,并在每次用户界面更改时运行它。
我添加了一个isUserDynamic
函数来替代isUser
来展示它是如何完成的,同时保持User
作为一个接口。以上是关于将 json 解析为 typescript 中的接口并检查是不是正常的主要内容,如果未能解决你的问题,请参考以下文章
在 Angular 应用程序中将 JSON 解析为 Typescript 类
如何在 Typescript 中保持代码 DRY 的同时解析多个 Json 文件?