Конечно, да, скажете вы. Но не было бы этой статьи, если бы не было вопроса.
Так же эта статья будет вам полезна, если вы используете эквайринг от Тинькофф.
Немного предыстории. Какое-то время назад на одном из своих проектов я поменял онлайн-эквайринг на Тинькофф и уже после отладки начали всплывать странные ошибки с оплатой: хэш-подпись запроса считалась неверно. Причем, только на реальных платежах, что еще больше омрачало ситуацию.
Проблема оказалась в поле Data json-объекта, который приходит от банка в нотификации платежа. В одних случаях оно приходит как Data, а в других DATA (в верхнем регистре).
О проблеме я сообщил в поддержку Тинькофф и тут началось интересное. Поддержка утверждает, что регистр ключей в JSON не играет никакой роли:
Валерий, здравствуйте, JSON не является регистрозависимым. С его точки зрения DATA и Data это одно и тоже. Корень проблемы тут в вашем программном обеспечении, которое как раз регистрозависимое.
К сожалению, доказать обратное техническим специалистам Тинькофф не удалось. Найти упоминание регистрозависимости JSON в спецификации — еще более сложная задача (нашли), поэтому я поступил так, как делаю всегда: пишу код и проверяю как он работает.
Поскольку JSON сам по себе ничего не значит, а всегда обрабатывается каким-либо языком программирования, можно легко узнать, как те или иные языки относятся к ключам в разном регистре в JSON.
JavaScript — как самый популярный
Когда говорят про JSON, самым популярным языком, его использующим, является JS.
const json = JSON.parse('{"Data":1,"DATA":2}'); console.log(json, json.Data); // {Data: 1, DATA: 2} 1
Как видим, регистр ключей играет роль. Два разных ключа с разными значениями. И если в документации указан ключ Data, то DATA не подойдет, увы.
PHP — когда нет JS
Возможно будет разница между массивом и объектом?
<?php $json = json_decode('{"Data":1,"DATA":2}', true); var_dump($json); // array (size=2) // 'Data' => int 1 // 'DATA' => int 2 $json = json_decode('{"Data":1,"DATA":2}', false); var_dump($json); // object(stdClass)[253] // public 'Data' => int 1 // public 'DATA' => int 2
Ситуация аналогичная. Ключи в разном регистре — это разные ключи. Преобразование в массив или в объект роли не играет.
Go — язык со строгой типизацией
Все же JS и PHP позволяют много вольностей. Возможно компилируемый язык со строгой типизацией будет вести себя иначе?
var data map[string]interface{} json.Unmarshal([]byte("{\"Data\":1,\"DATA\":2}"), &data) fmt.Println(data) // map[DATA:2 Data:1]
И снова ключи в разном регистре — это разные ключи. Мы получили map с двумя разными ключами и значениями.
C# — включаемая регистронезависимость
В комментариях выложили пример кода для C#
Поведение либо как у других языков, либо можно включить регистронезависимость и ловить ошибки при наложении свойств (хотя в случае одного свойства и правда не будет разницы).
Заключение
Если вы все еще сомневаетесь, является ли JSON регистрозависимым, просто попробуйте аналогичный код в своем языке программирования.
Я не встречал языка, в котором JSON был бы регистронезависимым. Если вы такой знаете — сообщите, будет интересно.
P.S. Я уверен, что разработчики Тинькофф тоже читают хабр. Обратите пожалуйста внимание на проблему. У вас на проде случайным образом меняется регистр ключа Data в нотификации платежа.
UPD 19.04.22 14:50
Спасибо @Busla за найденное упоминание регистрозависимости в спецификации.
ссылка на оригинал статьи https://habr.com/ru/post/661815/
Добавить комментарий