2015-07-01 1 views
0

У меня есть JSON строку, преобразованную из VDF (Valve Format Data) с регулярным выражением, как это:JSON объект регулярное выражение и слияние

{"items_game": { 
    "prefabs": { 
     ... 
     "coupon_crate_prefab": { 
      "prefab": "weapon_case_base", 
      "item_type": "coupon_crate", 
      "attributes": { 
       "cannot trade": "1" 
      }, 
      "capabilities": { 
       "can_delete": "0" 
      }, 
      "attributes": { 
       "expiration date": { 
        "attribute_class": "expiration_date", 
        "force_gc_to_generate": "1", 
        "use_custom_logic": "expiration_period_days_from_now", 
        "value": "2" 
       } 
      } 
     }, 
     "coupon_key_prefab": { 
      "prefab": "csgo_tool", 
      "item_type": "coupon_key", 
      "attributes": { 
       "cannot trade": "1" 
      }, 
      "capabilities": { 
       "can_delete": "0" 
      }, 
      "attributes": { 
       "expiration date": { 
        "attribute_class": "expiration_date", 
        "force_gc_to_generate": "1", 
        "use_custom_logic": "expiration_period_days_from_now", 
        "value": "2" 
       } 
      } 
     } 
     ... 
    } 
} 

Wanted результат:

 "coupon_key_prefab": { 
      "prefab": "csgo_tool", 
      "item_type": "coupon_key", 
      "attributes": { 
       "cannot trade": "1", 
       "expiration date": { 
        "attribute_class": "expiration_date", 
        "force_gc_to_generate": "1", 
        "use_custom_logic": "expiration_period_days_from_now", 
        "value": "2" 
       } 
      }, 
      "capabilities": { 
       "can_delete": "0" 
      } 
     } 

Как вы можете видеть, есть дубликаты attributes, и мне нужно объединить их, потому что это недействительно в JSON.
Как я могу это сделать? (Возможно, с preg_replace)

+2

Просто из любопытства, что происходит, когда вы десериализуете объект? Вы также должны отметить свой язык программирования, поскольку regex не решит вашу проблему, вам, скорее всего, придется обратиться к структуре данных в вашем коде. Кроме того, в зависимости от языка вы используете поведение сериализации, может быть разным. –

+0

@MikeBrant, после десериализации существуют только последние атрибуты. Да, я использую PHP. –

+0

Что касается вашей последней линии, не прыгайте на предвыборной площадке preg_replace. Это действительно ** никогда не рекомендуется использовать regexp для манипулирования json, поскольку он оставляет вас открытым для атак, особенно если ваш источник взломан. JSON - это кодировка с четко определенной и _context sensitive_ структурой. Если вам не удастся испортить структуру или ввести плохие данные, вы можете быть уверены, что хакер найдет способ. – Phil

ответ

3

Это очень плохая идея сделать это с помощью регулярного выражения, поскольку JSON - это структура данных, которая может быть отформатирована несколькими способами и делает такие вещи, как вложенность.

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

Но я также не уверен в достоверности того, что это делает - если вы запускаете JSON через валидатор, дубликаты ключей переписывают друг друга.

use strict; 
use warnings; 

use JSON; 

local $/; 
print to_json (from_json (<DATA>) , { pretty => 1 }); 

__DATA__ 
{ 
    "items_game": { 
     "prefabs": { 
      "coupon_crate_prefab": { 
       "prefab": "weapon_case_base", 
       "item_type": "coupon_crate", 
       "attributes": { 
        "cannot trade": "1" 
       }, 
       "capabilities": { 
        "can_delete": "0" 
       }, 
       "attributes": { 
        "expiration date": { 
         "attribute_class": "expiration_date", 
         "force_gc_to_generate": "1", 
         "use_custom_logic": "expiration_period_days_from_now", 
         "value": "2" 
        } 
       } 
      } 
     } 
    } 
} 

Это будет разобрать ваш JSON, который я надеюсь, что я исправил, чтобы соответствовать вашему источнику - обратите внимание, что это «затирается» часть ваших данных. Я думаю, что это обычное поведение в большинстве библиотек разбора. Таким образом, это может означать, что ваша «вещь» «обрабатывается» одинаково.

http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf

Так что трудно дать вам твердый ответ на то, что лучше всего делать с этим. В идеале вы должны использовать парсер JSON, но то, что вы делаете, не определено в спецификации JSON, поэтому вы получите переменные результаты.

Редактировать: После комментариев - кажется, VDF похож на JSON, но не довольно то же самое.

Я до сих пор не использовал регулярное выражение, но вместо этого мог бы попробовать рекурсивный синтаксический анализ. Выделите его { и «передайте» свой JSON-подобный контент, чтобы получить нижнюю ветку с именованными парами ключ-значение, которые вы затем можете удалить.

Если еще нет лучшего ответа, я могу взломать пример perl позже (извините, у меня нет времени на данный момент).

Вы можете найти то, что вы можете использовать здесь: http://www.perlmonks.org/?node_id=995856

Но это также может быть хорошим примером того, почему НЕ Regex это :)

+1

«Плохая идея сделать это с помощью регулярного выражения» - согласился! В том же ключе: с Regex и HTML, это одна и та же проблема. Http://stackoverflow.com/a/1732454/1143126 – RobertG

+0

Я конвертирую VDF в JSON с регулярным выражением, потому что эти форматы очень похожи. Но в VDF допустимо иметь одинаковые ключи в одном «объекте», в JSON это недопустимо. Также обновлен вопрос. –

+0

Действительно? Они думали, что что-то похожее на JSON_, но это - не совсем ... JSON - хорошая идея? Как ... раздражает. Там есть Perl VDF-парсер: https://github.com/killerfish/vdfparser PHP раздражает, идет к сломанной ссылке. – Sobrique

0

Ну, вы просили регулярное выражение. Является ли это возможным? Возможно, если у вас есть ограниченное количество вложенных элементов внутри вашего интересующего объекта. Это хорошая идея? №

(?<=\"attributes\":) (\{(?:(?:[^{]*?\{(?:[^{]|\n)*?\}[^{]*?)+|(?:[^{]|\n)*?)}) извлечет все данные атрибутов и позаботится об одноуровневых вложенных аргументах в вашем атрибуте, как показано https://regex101.com/r/rC3eK4/6.

Поскольку у вас только 1 уровень в вашем примере, он работает очень хорошо. Если вы хотите иметь 2 уровня, вам придется изменить его, добавив опцию из двух уровней и т. Д., Чтобы сохранить целостность всех {}. Возможно, существует лучший способ решить проблемы с регулярными выражениями в виде скобок, но это определенно не лучший инструмент для этого.

+0

Спасибо за ваш ответ Андрис. Я конвертирую VDF в JSON с регулярным выражением, потому что эти форматы довольно похожи. Но в VDF допустимо иметь одинаковые ключи в одном «объекте», в JSON это не так. Также обновлен вопрос. –