Конечно, да, скажете вы. Но не было бы этой статьи, если бы не было вопроса.

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

Немного предыстории. Какое-то время назад на одном из своих проектов я поменял онлайн-эквайринг на Тинькофф и уже после отладки начали всплывать странные ошибки с оплатой: хэш-подпись запроса считалась неверно. Причем, только на реальных платежах, что еще больше омрачало ситуацию.

Проблема оказалась в поле 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 за найденное упоминание регистрозависимости в спецификации.