示例: 目前,我们可以在地址名称属性中引用名称属性值,如下所示
{
person: {
name: "a",
address: {
name: { "$ref":"#/person/name"},
zip:"123"
}
}
}
有没有办法用相对路径引用相同的内容,如下所示。
{
person: {
name: "a",
address: {
name: { "$ref":"#/../name"},
zip:"123"
}
}
}
通过上面的问题是什么,我看到的是在当前的JSON那里是复杂的,多层次,如下面第一个代码段给出的参考值,任何一种简单的方法。为了从兄弟姐妹那里引用“ Name”属性,我必须从根开始提到一个完整的路径,尽管可以维护。如果层次结构中的更改很小,则该引用将不再有效。
{
"one": {
"two": {
"three": {
"four": {
"five": {
"fiveLevel1": {
"name": "foo"
},
"fiveLevel2": {
"name": {
"$ref": "#/one/two/three/four/five/fiveLevel1/name"
}
}
}
}
}
}
}
}
如果我们能够引用第二个片段中给出的相同属性,那么上层层次的更改将不会对引用产生任何影响,只有在“ FiveLevel1”和“ FiveLevel2”的同级中有直接更改时,更改才会发生“
{
"one": {
"two": {
"three": {
"four": {
"five": {
"fiveLevel1": {
"name": "foo"
},
"fiveLevel2": {
"name": {
"$ref": "#../fiveLevel1/name"
}
}
}
}
}
}
}
}
答案 0 :(得分:0)
香草JavaScript中不存在此功能,注释中对此也有说明。
但是,没有什么可以阻止您向对象添加循环引用,从而可以实现与所需内容接近的功能。您甚至可以将其包装在一个类中:
class RelPathObj {
constructor(obj) {
function build (parent, parentKey, obj) {
if (typeof obj === "object") {
for (let key in obj) {
if (typeof obj[key] === "object") {
parent[key] = { "..": parent, ...obj[key] };
build(parent[key], key, obj[key]);
} else {
if (key === "$ref") {
const path = obj[key].split("/");
Object.defineProperty(parent[".."],
parentKey,
{
get: function() {
let value = parent[".."];
path.forEach(p => { value = value[p] });
return value;
},
set: function(value) {
let ref = parent[".."];
path.forEach(p => {
if (typeof ref[p] === "object")
ref = ref[p]
else
ref[p] = value
});
}
});
} else {
parent[key] = obj[key];
}
}
}
} else {
parent = obj;
}
}
this.root = {};
build(this.root, "root", obj);
}
}
const relativePathObject = new RelPathObj({
"one": {
"two": {
"three": {
"four": {
"five": {
"fiveLevel1": {
"name": "foo"
},
"fiveLevel2": {
"name": {
"$ref": "../fiveLevel1/name"
}
}
}
}
}
}
}
});
let fiveLevel1 = relativePathObject["root"]["one"]["two"]["three"]["four"]["five"]["fiveLevel1"];
console.log(fiveLevel1.name);
let fiveLevel2 = fiveLevel1[".."]["fiveLevel2"];
console.log(fiveLevel2.name);
fiveLevel1.name = "bar";
console.log(fiveLevel2.name);
fiveLevel2.name = "baz"
console.log(fiveLevel1.name);
距离完美还很远,但是这里的主要思想是遍历对象的属性,在每个孩子中添加对父对象的引用,然后递归地重复此操作。找到$ref
时,它将解析路径并将其转换为其值。
当然,如果对象层次结构发生变化,则必须修复父级引用(可以在自定义类中实现)。
记住:这只是一个简单的代码段,向您展示了您可以做什么的想法,但我并没有考虑太多。 请勿在生产中使用它。