2016-09-20 3 views
3

私は、JSONはこのようなものになる可能性があり、このようなtypescript定義をjsonに解析するには?

namespace call.common { 
    namespace login { 
     interface Request { 
      userName: string; 
      password: string; 
     } 

     interface Response { 
      isLogin: boolean 
     } 
    } 
} 

として、JSONに私のtypescriptです定義を解析したい:私はコンパイラを使用しようとしています文書Using-the-Compiler-APIによる

{ 
    namespace: "call.common.login", 
    interfaces: [ 
     { 
      "name": "Request", 
      params: [{ 
       name: "userName", 
       type: "string", 
      }, { 
       name: "password", 
       type: "string" 
      }] 
     }, { 
      "name": "Response", 
      params: [{ 
       name: "isLogin", 
       type: boolean 
      }] 
     } 
    ] 
} 

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 
}); 
+0

をそして、どのようにあなたは、このJSONが見えるようになりよう:出力

node -e "console.log(JSON.stringify(require('./ts2json.js')('./eg.d.ts', {}), null, '\t'))" 

?どのようにそれを解析したいですか?もっと情報が役に立つかもしれません... –

+0

@NitzanTomer私が投稿したようなものですが、それは本当に簡単な例です – roger

答えて

0

コードに基づいてts2json.jsモジュールがあり、.d.tsファイルをプレーンJavaScに変換しますRIPTオブジェクト:

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]; 
}; 

あなたがJSON.stringify方法でJSON文字列を取得することができます。 次活字体定義ファイル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; 
    } 
} 

がでJSONを解析することができ、次の

{ 
    "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" 
      } 
     } 
    } 
}