JavaScript製のJSON用テンプレートエンジンの比較

JavaScriptから複雑なJSONを動的に生成するテンプレートエンジンを必要としているため、既存のライブラリを一通り調べてサンプルコードを列挙しました。
もしおすすめのライブラリをご存知でしたらコメントください。

目的としているテンプレートエンジンの仕様ですが、以下を必要としています。

- JSONまたは文字列をテンプレートとし、JSONを入力値とする
- 出力結果はJSON
- テンプレート中の指定キーワードをJSONの入力値で差し替える
- foreach/if/unless/optional などの制御構文を持つ


https://npmjs.com

から既存のライブラリを調査中です。


## json-templates

https://github.com/datavis-tech/json-templates

サンプル1:

```javascript
// Context values could be objects and arrays.
const template = parse("{{foo:baz}}");
console.log(template.parameters); // Prints [{ key: "foo", defaultValue: "baz" }]
console.log(template()); // Prints "baz", using the default value.
console.log(template({ foo: { value: 'bar' } }));
// Prints { value: 'bar' } , using the given value.
```

サンプル2:

```javascript
const template = parse({
    match: {
      title: "{{myTitle}}"
    }
});
console.log(template.parameters); // Prints [{ key: "myTitle" }]
console.log(template({ myTitle: "test" }));
// Prints { match: { title: 'test' } }
```

読み取れる大まかな仕様ですが、

- テンプレートは JSONまたは文字列
- 出力結果はJSONまたは文字列
- キーワード差し替え機能あり
- 制御構文なし

## json-templater

https://github.com/lightsofapollo/json-templater

``json-templates`` の派生ライブラリ。
機能を変えずに使い勝手を変えただけ。

サンプル1:

```javascript
let template = {
  "magic_key_{{magic}}": {
    "key": "interpolation is nice {{value}}"
  }
}
let object = require('json-templater/object');
console.log(object(
  template,
  { magic: 'key', value: 'value' }
));
// =>
// {
//  magic_key_key: {
//    key: 'interpolation is nice value'
//  }
//}
```

## @biothings-explorer/json-transformer

https://github.com/kevinxin90/json_transformer.js

サンプル1:

```javascript
const json_doc = {'ensemblgene': 1017};
// the template is a JSON object, with value as the field from json_doc to be transformed and the key as the field to be transformed to
const template = {'ensembl': 'ensemblgene'};
console.log(transform(json_doc, template));
// returns {'ensembl': 1017}
```

サンプル2:

```javascript
let json_doc = {
    'ensembl': {
        'gene': 1017
    },
    'wikipathway': [
        {
            'id': 'WP123',
            'name': 'aaa'
        },
        {
            'id': 'WP1234',
            'name': 'aaaa'
        }
    ]
};
let template = {
    'ensembl': 'ensembl.gene',
    'pathway': {
        'id': 'wikipathway.id',
        'name': 'wikipathway.name'
    }
};
let res = transform(json_doc, template);
//returns {'ensembl': 1017, 'pathway': [{'id': 'WP123', 'name': 'aaa'}, {'id': 'WP1234', 'name': 'aaaa'}]}
```

- テンプレートは JSON
- 出力結果はJSON
- キーワード差し替え機能あり
- 制御構文なし

## json-map-transform

https://github.com/edudavid/json-map-transform#readme

サンプル:

```javascript
const transform = require('json-map-transform');
const template = {
    title: {
        path: 'name',
        transform: (val) => val.toUpperCase()
    },
    label: {
        path: ['category', 'categories'],
        omitValues: ['', undefined, 'ERROR']
    },
    vendor: {
        path: 'meta.vendor',
        default: 'No vendor'
    },
    'meta.photos': {
        path: 'photos',
        transform: (val) => val.map(photo => photo.photoUrl)
    },
    'meta.id': {
        path: 'code'
    }
}
//The json objects to be transformed
const product1 = {
    name: 'Hello world',
    code: 'BOOK01',
    category: 'books',
    price: '200',
    photos: [ 
        { title: 'photo1', photoUrl: 'http://photo1.jpg', isCover: true },
        { title: 'photo2', photoUrl: 'http://photo2.jpg' }
    ],
    meta: {
        vendor: 'Author name'
    }
};
console.log(transform(product1, template)) 
// =>
// {
//   "title": "HELLO WORLD",
//   "label": "books",
//   "vendor": "Author name",
//   "meta": {
//      "photos": [
//         "http://photo1.jpg",
//         "http://photo2.jpg"
//      ],
//      "id": "BOOK01"
//    }
// }
```

- テンプレートは JSON
- 出力結果はJSON
- キーワード差し替え機能あり
- 制御構文なし
- テンプレート中に関数を直接記述できるのはちょっと面白い

## jsonpath-template

https://github.com/adamfowleruk/jsonpath-template

サンプル:

```javascript
const jpt = require('jsonpath-template');
var tplString = "Hello there [[$.person.name]], isn't it a [[$.daytype]] day?";
var json = {person:{name:"Adam"},daytype: "nice"};
var template = new jpt(tplString);
console.log(template.tags("[[","]]").apply(json));
// => Hello there Adam, isn't is a nice day?
```

- テンプレートはテキスト
- 出力結果はテキスト
- キーワード差し替え機能あり
- 制御構文なし
- タグの変更機能あり

## jsonapter

https://github.com/amida-tech/jsonapter

サンプル1:

```javascript
var bbj2j = require('jsonapter');
var j2j = bbj2j.instance();

var upper = function(input) {
	return input ? input.toUpperCase() : null;
};

var template = {
    content: {
        dest_a: {
            dataKey: 'a.c'
        },
        dest_b: {
            content: {
                dest_b0: {
                    value: upper,
                    dataKey: 'b.c'
                },
                dest_b1: {
                    value: upper,
                    dataKey: 'd'
                }
            },
            dataKey: 'a'
        }
    }
};

var input = {
    a: {
        b: {
            c: 'value_0'
        },
        c: 'value_2',
        d: 'value_1'
    }
};
 
var r = j2j.run(template, input);
console.log(r);
// => {dest_a: 'value_2', dest_b: {dest_b0: 'VALUE_0', dest_b1: 'VALUE_1'}}
```

サンプル2:

```javascript
var nameTemplate = {
    arrayContent: [{
        dataKey: 'familyName'
    }, {
        dataKey: 'givenName'
    }]
};
 
var template = {
    content: {
        name: nameTemplate,
        age: {
            value: function (input) {
                return 2015 - input;
            },
            dataKey: 'birthYear'
        }
    }
};
 
var r = j2j.run(template, {
    familyName: 'DOE',
    givenName: 'JOE',
    birthYear: 1980
});
console.log(r); // => {name: ['DOE', 'JOE'], age: 35}
```

サンプル3:

```javascript
var _ = require('lodash');
 
var template = {
    content: {
        dest_a: {
            dataKey: 'a'
        },
        dest_b: {
            dataKey: 'b',
            existsWhen: _.partialRight(_.has, 'c')
        }
    },
    existsWhen: 'public'
};
 
var r0 = j2j.run(template, {
    a: 'value_a',
    b: 'value_b',
    public: true
});
console.log(r0.dest_a); // => 'value_a'
console.log(r0.dest_b); // => undefined
 
var r1 = j2j.run(template, {
    a: 'value_a',
    b: 'value_b',
    c: 0,
    public: true
});
console.log(r1.dest_a); // 'value_a'
console.log(r1.dest_b); // 'value_b'
 
var r2 = j2j.run(template, {
    a: 'value_a',
    b: 'value_b',
    c: 0
});
console.log(r2); // null because public is not present
 
 
var r3 = j2j.run(template, {
    a: 'value_a',
    b: 'value_b'
  },
  {
    public: true,
    c: 0
  }
);
 
console.log(r3.dest_a); // => 'value_a'
console.log(r3.dest_b); // => 'value_b'
```

- テンプレートはJSON
- 出力結果はJSON
- キーワード差し替え機能あり
- **制御構文あり**
  - 書き方に癖がある
- lodashが必要？

## templatizejs

https://github.com/TLPcoder/templatizejs

サンプル:

```javascript
var templatize = require('templatizejs')
var json = {
    fizzBuzz: '{{fizz}}{{buzz}}',
}
 
var secondaries = [
    { fizz: 'Fizz' },
    { buzz: 'Buzz' }
]
 
console.log(templatize.json(json, secondaries))
// => { fizzBuzz: 'FizzBuzz' }
```


- テンプレートはJSON
- 出力結果はJSON
- キーワード差し替え機能あり
- 制御構文なし
- タグの変更機能あり


## qewd-transform-JSON

https://github.com/robtweed/qewd-transform-json

サンプル1:

```javascript
var inputObj = {
  foo: {
    bar1: 'hello',
    bar2: 'world' 
  }
};
var templateObj = {
  a: '{{foo.bar1}}',
  b: {
    c: '{{foo.bar2}}',
    d: 'literal text',
    e: 'hello {{foo.bar2}} again'
  }
};
var transform = require('qewd-transform-json').transform;
console.log(transform(templateObj, inputObj));
// => {
//    "a": "hello",
//    "b": {
//      "c": "world",
//      "d": "literal text",
//      "e": "hello world again"
//    }
//  }
```

配列処理:

```javascript
var inputObj = {
  foo: {
    bar1: 'hello',
    bar2: 'world' 
  },
  arr: [
    {
      name: 'Rob',
      city: 'London'
    },
    {
      name: 'Chris',
      city: 'Oxford'
    },
  ] 
};
var templateObj = {
  a: '{{foo.bar1}}',
  b: {
    c: '{{foo.bar2}}'
  },
  people: [
    '{{arr}}',
    {
      firstName: '{{name}}'
    }
  ]
};
var transform = require('qewd-transform-json').transform;
console.log(transform(templateObj, inputObj));
// =>  {
//    "a": "hello",
//    "b": {
//      "c": "world"
//    },
//    "people": [
//      {
//        "firstName": "Rob"
//      },
//      {
//        "firstName": "Chris"
//      }
//    ]
//  }
```

- テンプレートはJSON
- 出力結果はJSON
- キーワード差し替え機能あり
- **制御構文あり**
  - 書き方に癖がある
- テンプレート内に記述したJavaScriptを実行できる