2016-08-17 2 views
2

Я создаю приложение, основанное на данных, которые я получаю от API, сформированного как ответ, аналогичный функции json_encode(). Теперь я не знаю, как (я знаю, это возможно), что API время от времени возвращает дубликаты ключей. Поскольку это не мой сайт для исправления дубликатов ключей, я должен найти решение, как разобрать этот ответ в полезный массив, который содержит все данные, отправленные мне. Я хотел бы переименовать дубликаты ключей, добавив «x01», «x02», «x03» ... в свои ключи. До сих пор я нашел одно решение, которое могло бы помочь (here), но мне кажется, что это только для более простых массивов - я имею дело с вложенными массивами. Итак, вот ответ демо API:Разбор вложенных объектов JSON с дублирующимися ключами (PHP или JS)

{"boss":"mike", 
    "employees":{ 
     "Josh":{ 
      "active":"1", 
      "hours":"12", 
      "name":"Josh"}, 
     "Josh":{ 
      "active":"1", 
      "hours":"3", 
      "name":"Josh"} 
    } 
} 

Итак, как вы можете видеть, почти весь ключ «Джош» дублируется (в «часы» к югу клавиши за исключением). Несмотря на то, что это похоже на ошибку, для меня важны обе значения. Итак, это массив, который я хотел бы получить:

array (
    "boss" => "mike", 
    "employees" = array (
    "x01Josh" = array ("active" => "1", "hours" => "12", "name" => "Josh") 
    "x02Josh" = array ("active" => "1", "hours" => "3", "name" => "Josh") 
) 
) 

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

Поскольку я новичок в RegEx, и так как я не нашел решения с этим (я уверен, что он существует, но мне его не удалось найти), я прошу вас о помощи.

Я планирую анализировать его либо в JavaScript/jQuery, либо в PHP (используя другой запрос JSON). Спасибо заранее.

ОБНОВЛЕНИЕ Я забыл упомянуть - причина, по которой я делаю это, состоит в том, что второй ключ перезаписывает первый (дубликат). Кроме того, я не могу изменить API (это не API моего сайта). Я уже попросил их внести некоторые изменения в эти проблемы, но тем временем я должен сделать это с моей стороны.

+2

в JavaScript дубликат ключа перезаписывает первый , в строгом режиме он возвращает ошибку. –

+0

- вот почему мне нужно каким-то образом разобрать его, чтобы его можно было использовать без ошибок или перезаписи. – agapetos

+0

Эти дублированные ключи точно соответствуют друг другу? – revo

ответ

2

В решение JS с помощью String.replace, String.match, Array.filter и Array.shift функции:

var jsonData = '{"boss":"mike","employees":{"Josh":{"active":"1","hours":"12","name":"Josh"},"Josh":{"active":"1","hours":"3","name":"Josh"}}}', 
 
    re = /\"(\w+?)(?=\":\{)/g, names = {}, dups; 
 

 
jsonData.match(re).forEach(function(v){ 
 
    v = v.replace(/\"/, ""); 
 
    (!names[v])? names[v] = 1 : names[v]++; 
 
}); 
 

 
dups = Object.keys(names).filter(function(k) { return names[k] > 1; }); // getting duplicated keys 
 
dups.forEach(function (k) { 
 
    var count = names[k], i; 
 
    names[k] = []; 
 

 
    for (i = 0; i < count; i++) { 
 
     names[k].push("x0" + (i+1)); 
 
    } 
 
}); 
 

 
jsonData = jsonData.replace(re, function (p1) { // replacing duplicate keys 
 
    p1 = p1.substr(1); 
 
    if (dups.indexOf(p1) !== -1) { 
 
     return '"' + names[p1].shift() + p1; 
 
    } else { 
 
     return '"' + p1; 
 
    } 
 
}); 
 

 
console.log(JSON.parse(jsonData));

+0

Это работает как шарм, и все, что вы написали, показывает точно так, как должно быть на основе данной строки. Однако, когда я пробовал свою настоящую строку API, это не сработало, потому что у ключа был период внутри имени («agapetos .main ") .Когда я пробовал просто« agapetos », все работало красиво. Можно ли добавить это к функции, которую нельзя отбрасывать на какой-то период? – agapetos

+0

Я действительно (не демонстрационный, упрощенный) выглядит как это: {"username": "agapetos", "workers": {"agapetos.main": {"alive": "1", "hashrate": "8351", "username": "agapetos.main"}, «agapetos.main»: {«live»: «1», «hashrate»: «22668», «username»: «agapetos.main»}}} – agapetos

+1

@agapetos, хорошо, я сделаю это после тренировки (если у вас пока нет другого решения) – RomanPerekhrest

1

Невозможно ли изменить API? То, что вы разместили, не является JSON. Он возвращает карту с дублирующимися ключами, а не массив объектов.

Если вам нужно «работать с тем, что вы получаете». Тогда вам, вероятно, потребуется изучить собственный парсер. Использование регулярных выражений для вложенных структур не является идеальным.

+0

Я также понимаю, что они (владелец сайта, владеющего API) не кодировали его с помощью json_encode(), а скорее каким-то образом создали его. Как вы говорите, мне нужно работать с тем, что я получаю. И это именно то, о чем идет речь в этой статье - как сделать хороший парсер для подобных ситуаций. Я старался сделать это, анализируя слова один, используя функции PHP, с которыми мне удобно. Но, поскольку я все еще не так хорош в регулярном выражении, мне может потребоваться время, чтобы придумать хороший парсер или несколько часов, чтобы придумать огромный неэффективный код. – agapetos

+0

Будет ли [это решение] (http://stackoverflow.com/a/30845581/6693643) помочь? – Dhananjay

+0

@agapetos Я бы, вероятно, посмотрел на создание своего собственного автомата для разбора строки «JSON». Проверка того, обрабатывает ли он ключ или значение и создает эквивалент в PHP. С добавленным примечанием, что значение для сотрудников должно быть массивом, а не картой. – nolan

0

Попробуйте как этот

{"boss":"mike", 
    "employees":[ 
     { 
      "active":"1", 
      "hours":"12", 
      "name":"Josh"}, 
     { 
      "active":"1", 
      "hours":"3", 
      "name":"Josh"} 
    ] 
} 
+0

Это было бы приемлемо и здорово ... и это результат, который я пытаюсь выполнить. Есть ли у вас какая-то рекомендация о том, как получить от API, который я получаю, к результату, который вы написали? – agapetos

Смежные вопросы