JSONReader
is a JSON reader that support a smart way to migrate JSON (or JavaScript object). You can write migration plan and read old json easily. So that you may use it to read old json config, NoSQL entity or whatever.
JSON Version 1 (user.json
)
{
"id": 5,
"full_name": "Harmony Kim",
"age": 26
}
JSON Version 2 (user-v2.json
)
{
"id": "5",
"first_name": "Harmony Kim",
"last_name": null,
"age": 26
}
JSON Version 3 (user-v3.json
)
{
"id": "5",
"first_name": "Harmony",
"last_name": "Kim",
"email": null
}
Migration Plan migration.js
[
{
from: null,
to: {version: 2},
mappings: {
"id": T.Convert("id", "string"),
"first_name": T.Rename("full_name"),
"last_name": null
}
},
{
from: {version: 2},
to: {version: 3},
mappings: {
"email": null, // for old json, set to null as default value
"age": T.Drop() // remove the key-value pair
}
}
]
Then you can load the json in latest format no matter what version the json is.
// (Objective-C) Code that loads version 1 of the json.
NSDictionary *userJSON = [JSReader dictionaryWithJSONPath:[[NSBundle mainBundle] pathForResource:"user" ofType:@"json"]
migrationPlanPath:[[NSBundle mainBundle] pathForResource:"migration" ofType:@"js"]];
// What you read...
{
"id": "5",
"first_name": "Harmony Kim",
"last_name": null,
"email": null
}
-
It supports default value for newly added key-value pair.
{ from: {"version": 2}, to: {"version": 3}, mappings: { "new_key": "any default value you like" } }
-
It supports inline transformation in Javascript.
{ from: {"version": 2}, to: {"version": 3}, mappings: { "new_name": function (o) { return "name_" + o.toUpperCase(); } } }
-
It supports array migration.
{ from: {"version": 2}, to: {"version": 3}, mappings: { "emails": T.Convert("email", "array") } }
-
You can add
version
field in later version. So that you can use this library on older projects.{ from: null, to: {"version": 3}, mappings: { // ... } }
-
You can use different method to determine the version.
{ from: {"v": "2"}, to: {"version": 3} }
or even...
{ from: {"v1": function (json) { return "full_name" in json; }}, to: {"version": 2} }
-
Multilingual ;-)
// Objective-C NSDictionary *newJSON = [JSReader dictionaryWithJSONPath:[NSBundle pathForResource:"user" ofType:@"json"] migrationPlanPath:[NSBundle pathForResource:"migration" ofType:@"js"]];
// Javascript var newJSON = JSReader.read(oldJSONContent, migrationPlan);
-
It supports identity transform (do nothing).
{ from: {"version": 2}, to: {"version": 3} }
-
It can prevent the new json from inheriting old value.
{ from: {"version": 2}, to: {"version": 3}, inheritItems: false, // default: true mappings: { // ... } }
-
It supports nested array migration.
Old version JSON
[ { "name": "Thomas", "borrowed_movie_list": [ { "id": 5311, "name": "500 Days of Summer" }, { "id": 8812, "name": "Inception" } ] } ]
New version JSON
[ { "name": "Thomas", "borrowed_items": [ { "id": 5311, "title": "500 Days of Summer", "type": "movie" }, { "id": 8812, "title": "Inception" "type": "movie" } ] } ]
// migration.js { from: {"version": 2}, to: {"version": 3}, array_mappings: { "*.borrowed_items": T.Rename("*.borrowed_movie_list", { "*.type": "movie", "*.title": T.Rename("*.name") }) } }
It is equivalent to this migration script:
// migration-2.js { from: {"version": 2}, to: {"version": 3}, array_mappings: { "*.borrowed_items": T.Rename("*.borrowed_movie_list"), "*.borrowed_items.*.type": "movie", "*.borrowed_items.*.title": T.Rename("*.borrowed_items.*.name") } }
- TODO: ///
- implement everything ;-)