I want to parse my typescript definition to json, such as
namespace call.common {
namespace login {
interface Request {
userName: string;
password: string;
}
interface Response {
isLogin: boolean
}
}
}
the json could be something like this:
{
namespace: "call.common.login",
interfaces: [
{
"name": "Request",
params: [{
name: "userName",
type: "string",
}, {
name: "password",
type: "string"
}]
}, {
"name": "Response",
params: [{
name: "isLogin",
type: boolean
}]
}
]
}
According to the document Using-the-Compiler-API
I am trying to use compiler:
function parseGrpcTypings(fileName, options) {
var program = ts.createProgram(fileName, options);
var checker = program.getTypeChecker();
const sourceFile = program.getSourceFiles()[0];
ts.forEachChild(sourceFile, visit);
function visit(node) {
if (!isNodeExported(node)) {
return;
}
if (node.kind === ts.SyntaxKind.ModuleDeclaration) {
ts.forEachChild(node, visit);
} else if (node.kind === ts.SyntaxKind.InterfaceDeclaration) {
// how to parse interface
} else {
// how to deal with namespace
}
}
function isNodeExported(node) {
return (node.flags & ts.NodeFlags.Export) !== 0 || (node.parent && node.parent.kind === ts.SyntaxKind.SourceFile);
}
}
parseGrpcTypings("/tmp/test.d.ts", {
target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
});
Use the JSON. parse() method to parse a JSON string in TypeScript, e.g. const result: Person = JSON. parse(jsonStr) . The method parses a JSON string and returns the corresponding value.
To parse a JSON string in TypeScript, you can use JSON. parse().
Based on your code, here is a ts2json.js
module that turns .d.ts
file into plain JavaScript objects:
const ts = require('typescript');
const PROPERTY_TYPES = {
any: ts.SyntaxKind.AnyKeyword,
boolean: ts.SyntaxKind.BooleanKeyword,
number: ts.SyntaxKind.NumberKeyword,
string: ts.SyntaxKind.StringKeyword,
};
class TSNode {
constructor(name, type) {
this.children = [];
this.addChildren = (name, type) => {
let node = new TSNode(name, type);
this.children.push(node);
return node;
};
this.getType = () => this.type;
this.getObject = () => {
let map = {};
map[this.name] = this.children.length
? this.children
.map(child => child.getObject())
.reduce((pv, child) => {
for (let key in child) {
if (pv.hasOwnProperty(key) || key in pv) {
Object.assign(pv[key], child[key]);
} else {
pv[key] = child[key];
}
}
return pv;
}, {})
: this.type;
return map;
};
this.name = name;
this.type = type;
}
}
let visit = parent => node => {
switch (node.kind) {
case ts.SyntaxKind.ModuleDeclaration:
let moduleName = node.name.text;
ts.forEachChild(node, visit(parent.addChildren(moduleName)));
break;
case ts.SyntaxKind.ModuleBlock:
ts.forEachChild(node, visit(parent));
break;
case ts.SyntaxKind.InterfaceDeclaration:
let interfaceName = node.name.text;
parent[interfaceName] = {};
// console.log('interface');
ts.forEachChild(node, visit(parent.addChildren(interfaceName)));
break;
case ts.SyntaxKind.PropertySignature:
let propertyName = node.name;
let propertyType = node.type;
let arrayDeep = 0;
let realPropertyName =
'string' !== typeof propertyName && 'text' in propertyName
? propertyName.text
: propertyName;
while (propertyType.kind === ts.SyntaxKind.ArrayType) {
arrayDeep++;
propertyType = propertyType.elementType;
}
if (propertyType.kind === ts.SyntaxKind.TypeReference) {
let realPropertyType = propertyType.typeName;
parent.addChildren(
realPropertyName,
'Array<'.repeat(arrayDeep) +
(realPropertyType.kind === ts.SyntaxKind.QualifiedName
? realPropertyType.getText()
: 'text' in realPropertyType
? realPropertyType.text
: realPropertyType) +
'>'.repeat(arrayDeep)
);
} else {
for (let type in PROPERTY_TYPES) {
if (propertyType.kind === PROPERTY_TYPES[type]) {
parent.addChildren(realPropertyName, type);
break;
}
}
}
break;
default:
}
};
module.exports = function(filename, options) {
const ROOT_NAME = 'root';
const node = new TSNode(ROOT_NAME);
let program = ts.createProgram([filename], options);
let checker = program.getTypeChecker();
let sourceFile = program.getSourceFiles()[1];
ts.forEachChild(sourceFile, visit(node));
return node.getObject()[ROOT_NAME];
};
You can get the JSON string with JSON.stringify
method.
The following TypeScript definition file eg.d.ts
:
declare namespace School.Users {
interface User {
lastName: string;
firstName: string;
email: string;
}
interface Student extends User {
graduation: number;
mainTeacher: Teacher;
}
interface Teacher extends User {
classes: Student[][];
room: School.Building.Room;
}
}
declare namespace School.Building {
interface Room {
name: string;
}
}
Can be parsed to JSON with the following:
node -e "console.log(JSON.stringify(require('./ts2json.js')('./eg.d.ts', {}), null, '\t'))"
That outputs:
{
"School": {
"Users": {
"User": {
"lastName": "string",
"firstName": "string",
"email": "string"
},
"Student": {
"graduation": "number",
"mainTeacher": "Teacher"
},
"Teacher": {
"classes": "Array<Array<Student>>",
"room": "School.Building.Room"
}
},
"Building": {
"Room": {
"name": "string"
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With