Как создать ключевой массив из вложенного JSON по определенному значению с помощью lodash или без lodash?

Попробуйте выполнить следующий код для анализа вашего ответа php json: read.php

<script
  src="https://code.jquery.com/jquery-3.2.1.min.js"
  integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
  crossorigin="anonymous"></script>
<script type="text/javascript">  
$.ajax({
    url:'index.php',
    data:{},
    type:"POST",
    success:function(result) {
        jsondecoded = $.parseJSON(result);
        $.each(jsondecoded, function(index, value) {
            $("#servers").text($("#servers").text() + " " + value.servername);
            console.log(value.start);
            console.log(value.end);
            console.log(value.id);
        });
    },
    statusCode: {
    404: function() {
      alert( "page not found" );
    }
  }
});
</script>

server.php

<?php 
echo '[{"start":"2017-08-29","end":"2017-09-01","id":"22"},{"start":"2017-09-03","end":"2017-09-06","id":"23"}]';
?>
-2
задан Mehul Mali 13 July 2018 в 08:57
поделиться

7 ответов

Если вы можете написать рекурсивную функцию, которая лучше всего подходит для производительности.

Но если вы хотите пропустить рекурсивный вызов с (для каждого ключа в вложенном объекте), вы можете попробовать JSON.parse с дополнительным параметром (обратный вызов), который будет называться рекурсивно. как обобщенное решение, я добавляю фрагмент (с JSON.parse, предполагая, что помощь в написании рекурсивной функции не должна быть принята / часть этого ответа).

Но помните, ЕСЛИ вы беспокоитесь о производительности эффективность вы не должны использовать это, поскольку вы должны стягивать (может быть большой объект) и снова анализировать. Но если у вас есть строка JSON, это должно быть одним из лучших решений.

var anyObject = [
  {
    "Attr": [
      {
        "power": { "p1": "str", "t3": "str" },
        "light": [
          {"test": "str"},
          {"test2": [ { "t4": "str" }]}
        ]
      }
    ]
  },
  {
    "Attr1": [
      {
        "power1": { "p2": "str", "t5": "str" },
        "light1": [
          { "test3": "str" },
          { "test_x": [
              { "t_x": "str" },
              { "t_y": [
                  { "t_y1": "str" }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

function getKeys(obj, str) {
let resultArr = [];
	JSON.parse(JSON.stringify(obj), (key, val) => {
		if(val === str) { resultArr.push(key) }
		return val;
	} )
return resultArr;
}

console.log(getKeys(anyObject, 'str'))

Это не зависит от конкретного случая, вы можете есть все ключи, если вы передадите другой обратный вызов в JSON.parse, а также можете преобразовать объект с помощью этого (возвращаемое преобразованное значение вместо фактического значения)

И если вы хотите использовать lodash для повторного итерации объекта, то вы можете использовать _.cloneDeepWith для рекурсивного итерации объекта.

Вот рабочий пример:

let anyObject = [
  {
    "Attr": [
      {
        "power": { "p1": "str", "t3": "str" },
        "light": [
          {"test": "str"},
          {"test2": [ { "t4": "str" }]}
        ]
      }
    ]
  },
  {
    "Attr1": [
      {
        "power1": { "p2": "str", "t5": "str" },
        "light1": [
          { "test3": "str" },
          { "test_x": [
              { "t_x": "str" },
              { "t_y": [
                  { "t_y1": "str" }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
];

function getKeys(obj, str) {
  let resultArr = [];
  _.cloneDeepWith(obj, (value, key) => { value === 'str' && resultArr.push(key)});
  return resultArr;
}

console.log(getKeys(anyObject, 'str'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

1
ответ дан Koushik Chatterjee 17 August 2018 в 13:21
поделиться

IMHO, вы ищете что-то вроде этого:

var testArr = [{"Attr":[{"power":{"p1":"str","t3":"str"},"light":[{"test":"str"},{"test2":[{"t4":"str"}]}]}]},{"Attr1":[{"power1":{"p2":"str","t5":"str"},"light1":[{"test3":"str"},{"test_x":[{"t_x":"str"},{"t_y":[{"t_y1":"str"}]}]}]}]}];


var strFind = (arr, accumulator = []) => {
  arr.forEach(obj => {
    Object.entries(obj).forEach(([key, value]) => {
      if (value === "str") accumulator.push(key);
      if (Array.isArray(value)) strFind(value, accumulator);
      if (key.includes("power")) {
        Object.entries(value).forEach(([cKey, cValue]) => {
          if (cValue === "str") accumulator.push(cKey);
        })
      }
    });
  })
  return accumulator;
}

console.log(strFind(testArr));

1
ответ дан BlackBeard 17 August 2018 в 13:21
поделиться

Вот еще одна возможность, использующая естественно рекурсивный характер JSON.stringify:

const input = [{"Attr":[{"power":{"p1":"str","t3":"str"},"light":[{"test":"str"},{"test2":[{"t4":"str"}]}]}]},{"Attr1":[{"power1":{"p2":"str","t5":"str"},"light1":[{"test3":"str"},{"test_x":[{"t_x":"str"},{"t_y":[{"t_y1":"str"}]}]}]}]}];

const output = [];
JSON.stringify(input, (key, val) => {
  if (val === 'str') output.push(key);
  return val;
});
console.log(output);

0
ответ дан CertainPerformance 17 August 2018 в 13:21
поделиться

Еще одна попытка использования JSON.stringify и синтаксического анализа строк:

const result = JSON.stringify(data)
  .match(/"[^"]+":"str"/g) // get all "xxx":"str" pairs
  .map(r => r.substring(1, r.indexOf(':') - 1)); // pick out all "xxx"

console.log(result);
// ["p1", "t3", "test", "t4", "p2", "t5", "test3", "t_x", "t_y1"]
0
ответ дан dhilt 17 August 2018 в 13:21
поделиться
  • 1
    Будет ли это работать, если какое-либо значение ключа содержит `: & quot; str & quot;` – Koushik Chatterjee 13 July 2018 в 09:02
  • 2
    @KoushikChatterjee Вы правы, процедура должна быть изменена для обработки ключей, содержащих ': str' – dhilt 13 July 2018 в 09:15
  • 3
    Если вы собираетесь использовать регулярное выражение, .map не нужно, используйте вместо него lookahead. – CertainPerformance 13 July 2018 в 09:33

Попробуйте что-то вроде этого:

var array = [];
function searchForStringInJsonRecursive (jsonData, str) {
    for(var i in jsonData) {
        // If the element is an Array or nested object continue to search
        if (typeof jsonData[i] === 'object') {
            searchForStringInJsonRecursive(jsonData[i], str);
        }
        // If the element is not an Object and matches str add the it to the array
        else if (jsonData[i] === str) {
            array.push(i);
        }
    }
}

Предполагая, что ваш json находится в переменной с именем data, вы можете вызвать функцию следующим образом: searchForStringInJsonRecursive(data, 'str'); array будет содержать все ключи, которые соответствие содержимого 'str'

0
ответ дан ElBullet 17 August 2018 в 13:21
поделиться

Вот один из способов: lodash:

var testArr = [{"Attr":[{"power":{"p1":"str","t3":"str"},"light":[{"test":"str"},{"test2":[{"t4":"str"}]}]}]},{"Attr1":[{"power1":{"p2":"str","t5":"str"},"light1":[{"test3":"str"},{"test_x":[{"t_x":"str"},{"t_y":[{"t_y1":"str"}]}]}]}]}];

var findStr = function(o) {
  return _(o)
  	.map(function(v, k) {
    	  return v === 'str'
      	    ? k
      	    : _.isObject(v) ? findStr(v) : null;
  	})
  	.compact()
        .flatten()
  	.value();
};

console.log(findStr(testArr));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

0
ответ дан IronGeek 17 August 2018 в 13:21
поделиться

Я сделал это ... Я использовал lodash. Мой код выглядит следующим образом:

var arrayData = [];
var teatData = [
  {
    "Attr": [
      {
        "power": { "p1": "str", "t3": "str" },
        "light": [
          {"test": "str"},
          {"test2": [ { "t4": "str" }]}
        ]
      }
    ]
  },
  {
    "Attr1": [
      {
        "power1": { "p2": "str", "t5": "str" },
        "light1": [
          { "test3": "str" },
          { "test_x": [
              { "t_x": "str" },
              { "t_y": [
                  { "t_y1": "str" }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
];

function getKeyArray(data, arrayData) {
    if (Array.isArray(data)) {
      _.forEach(data, (obj, key) => {
        this.getKeyArray(obj, arrayData);
      });
    } else if (_.isPlainObject(data)) {
      _.forEach(data, (obj, key) => {   
        if (obj === "str") {
          arrayData.push(key);
        } else if (Array.isArray(obj) || _.isPlainObject(obj)) {
          this.getKeyArray(obj, arrayData);
        }
      });
    }
  }
  
  getKeyArray(teatData, arrayData);
  
  console.log(arrayData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script>

0
ответ дан Mehul Mali 17 August 2018 в 13:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: