LoginSignup
1
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-03-16

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

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

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

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

json-templates

サンプル1:

// 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:

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

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

サンプル1:

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

サンプル1:

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:

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

サンプル:

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

サンプル:

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

サンプル1:

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:

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:

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

サンプル:

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

サンプル1:

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

配列処理:

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を実行できる
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0