JSON неопределенное свойство - упрощенная проверка, чтобы избежать TypeErrors - PullRequest
0 голосов
/ 07 февраля 2019

Я пытаюсь эффективно проверить многослойные объекты json, которые могут иметь одно или несколько неопределенных родительских свойств в зависимости от сценария.

Это пример и объект только двух уровней свойств:

    scenarioArray = [ 
    {color:{blue:'yes'}},
    {color:{green:'no'}},
    {colour:{blue:'yes'}} ]; //colour instead of color

Поэтому я хочу наиболее эффективно определить цвет сценария


    let color;
    let s = randomScenario; //random scenario from the scenarioArray
    if(s.color != undefined && s.color.blue != undefined){
        color = s.color.blue;
    }else if (s.color != undefined && s.color.green != undefined){
        color = s.color.green;
    }else if (s.colour != undefined && s.colour.blue !=undefined){
        color = s.colour.blue;
    };

Этот код техническиработает, это просто грязно.

Когда вы экстраполируете это на объекты с 4-5 уровнями свойств, операторы if становятся громоздкими и нечитаемыми.

Мне бы очень хотелось посоветовать, как это просто.

примеры реальных объектов json:

    addendum.contract.buyerInformation.name 
    addendum.contract.contract.buyerInformation.name
    addendum.contract.purchaser.buyerFirstName
    addendum.contract.data.purchaser.buyer.name

используемые платформы / библиотеки: AngularJS Lodash (открыт для любых предлагаемых библиотек, которые могут сделать это более эффективным)

PS пожалуйстадайте мне знать, если это слишком открытый конец вопроса для stackOverflow ...

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

К сожалению, в JavaScript отсутствует собственная автовивификация , но в некоторой степени его можно эмулировать с помощью Proxy.

Это неудобное и хрупкое решение, ноон сокращает любую глубокую проверку до двух действий и должен работать в большинстве случаев:

'use strict';

const isEmpty = Symbol('isEmpty');

function autoVivify(object = {}) {
  Object.defineProperty(object, isEmpty, {
    get: () => Object.keys(object).length === 0,
  });

  Object.keys(object).forEach((key) => {
    const val = object[key];
    if (typeof val === 'object' && val !== null) object[key] = autoVivify(val);
  });

  return new Proxy(
    object,
    { get: (obj, name) => name in obj ? obj[name] : obj[name] = autoVivify() },
  );
}

const scenarioArray = [
    { color: { blue: 'yes' }},
    { color: { green: 'no' }},
    { colour: { blue: 'yes' }},
];

const randomScenario = autoVivify(scenarioArray[0]);

if (randomScenario.color.blue && !randomScenario.color.blue[isEmpty])
  console.log(randomScenario.color.blue);

if (randomScenario.color.red && !randomScenario.color.red[isEmpty])
  console.log(randomScenario.color.red);

if (randomScenario.color.a.b.c && !randomScenario.color.a.b.c[isEmpty])
  console.log(randomScenario.color.a.b.c);

if (randomScenario.colour.green && !randomScenario.colour.green[isEmpty])
  console.log(randomScenario.colour.blue);

Будем надеяться, что у нас будет более подходящий способ в ближайшее время.

0 голосов
/ 08 февраля 2019

Вот функция, которая может найти ошибки для вас.Поддерживает до трех уровней.это настраивается.для 4-го и 5-го уровней вы можете расширить его или сделать его рекурсивным для поддержки неограниченного уровня:

const validSecondLevels = ['blue', 'red', 'green']
const validThirdLevels = ['yes', 'no']
const validPropertyNames = ['color']


scenarioArray = [
    { color: { bluee: 'yes' } },
    { color: { green: 'invalid-value' } },
    { colour: { blue: 'yes' } }];

function findErrors(scenario) {
    var invalidProperties = scenarioArray.filter(function (it) {

        var invalidPropertyNames = Object.keys(it).filter(item => !validPropertyNames.includes(item));

        if (invalidPropertyNames.length)
            return it;

        var foundProperties = validPropertyNames.filter(item => it[item]).map(item => it[item]);

        var invalids = foundProperties.filter(function (property) {

            var invalidSecondLevels = Object.keys(property).filter(item => !validSecondLevels.includes(item));

            if (invalidSecondLevels.length)
                return property;

            var foundValues = validSecondLevels.filter(item => property[item]).map(item => property[item]);

            var invalidThirdLevels = foundValues.filter(function (foundValue) {
                return !validThirdLevels.includes(foundValue);
            });

            if (invalidThirdLevels.length)
                return property;

        });

        if (invalids.length)
            return it;

    });

    return invalidProperties;
}

console.log(findErrors(scenarioArray));
...