Есть ли способ использовать указатели JSON для использования относительного пути в боковой строке JSON? - PullRequest
0 голосов
/ 31 января 2019

Пример: В настоящее время мы можем ссылаться на значение свойства name в свойстве address name, как показано ниже.

{
        person: { 
            name: "a",
            address: {
                name: { "$ref":"#/person/name"},
                zip:"123"
            }
        }
  }

. Есть ли способ ссылаться на это с помощью относительного пути, как показано ниже.

{
        person: { 
            name: "a",
            address: {
                name: { "$ref":"#/../name"},
                zip:"123"
            }
        }
  }

СВыше вопрос, на который я смотрю, это простой способ ссылаться на любое значение в текущем json, где есть сложные и множественные иерархии, как показано ниже в первом фрагменте кода.Для ссылки на свойство «Имя» от одноуровневого элемента я должен упомянуть полный путь прямо из корня, который можно поддерживать.Если в иерархической структуре есть небольшое изменение, ссылка больше не будет действительной.

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

1 Ответ

0 голосов
/ 15 апреля 2019

Эта функция не существует в обычном 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, он анализирует путь и переводит его в его значение.

Конечно, если иерархия объектов изменится, вам придется исправить родительские ссылки (это то, что вы могли бы реализовать вВаш пользовательский класс).

Запомните: это всего лишь простой фрагмент кода, чтобы показать вам идею того, что вы можете сделать, я не особо задумывался над этим. Не используйте его в производстве .

...