За последние 24 часа нас посетил 20841 программист и 1135 роботов. Сейчас ищут 330 программистов ...

Обновление данных в файле json

Тема в разделе "PHP для новичков", создана пользователем koresh, 12 июл 2019.

Метки:
  1. koresh

    koresh Новичок

    С нами с:
    11 июл 2019
    Сообщения:
    19
    Симпатии:
    0
    Здравствуйте!
    Помогите пожалуйста решить проблему - у меня есть файл kursNBU.json с таким содержимым:
    Код (Text):
    1. [
    2.     {
    3.         "r030":643,"txt":"Російський рубль","rate":0.40877,"cc":"RUB","exchangedate":"15.07.2019"
    4.     },
    5.     {
    6.         "r030":840,"txt":"Долар США","rate":25.760584,"cc":"USD","exchangedate":"15.07.2019"
    7.     },
    8.     {
    9.         "r030":933,"txt":"Бiлоруський рубль","rate":12.66374,"cc":"BYN","exchangedate":"15.07.2019"
    10.     },
    11.     {
    12.       "r030":978,"txt":"Євро","rate":28.988385,"cc":"EUR","exchangedate":"15.07.2019"
    13.     }
    14. ]
    В этих данных ключ это "r030", он обозначает код валют и является статическим.

    Я создал задачу cron которая запускает скрипт который должен обновить значения для ключей "rate" и "exchangedate".
    Вот мой код:
    PHP:
    1. <?php
    2.  
    3. $json = @file_get_contents("https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json");
    4.  
    5. if ( $json !== false )
    6. {
    7.     $kurs_new = json_decode($json);
    8.    
    9.     $cron_curs = file_get_contents( __DIR__ . "/cursNBU.json");
    10.     $kurs_old = json_decode($cron_curs);
    11.    
    12.  
    13.     foreach ( $kurs_new as $cur )
    14.     {
    15.         foreach ( $kurs_old as $item )
    16.         {
    17.             if ( $item->r030 == $cur->r030 )
    18.             {
    19.                 $item->rate = $cur->rate;
    20.                 $item->exchangedate = $cur->exchangedate;
    21.             }
    22.         }
    23.     }
    24. }
    25.  
    26. // преобразовываем его в json вид
    27. $json_new = json_encode($kurs_old);
    28.  
    29. // открываем файл
    30. $file = fopen(__DIR__ . '/kursNBU.json', 'w');
    31.  
    32. // и записываем туда данные
    33. $write = fwrite($file, $json_new);
    34.  
    35. //закрываем файл
    36. fclose($file);
    37.  
    38. // Очистить переменные
    39. unset($kurs_new);
    40. unset($kurs_old);
    В итоге после выполнения cron задачи в файле kursNBU.json всё полностью стирается и записывается значение null

    Файл php и файл json лежат рядом в одной папке.
     
  2. master-web

    master-web Новичок

    С нами с:
    29 май 2019
    Сообщения:
    44
    Симпатии:
    16
    Файл у вас kursNBU.json, а прочитать пытаетесь
    PHP:
    1. $cron_curs = file_get_contents( __DIR__ . "/cursNBU.json");
     
    koresh нравится это.
  3. koresh

    koresh Новичок

    С нами с:
    11 июл 2019
    Сообщения:
    19
    Симпатии:
    0
    Спасибо!

    Теперь обновление файла идёт, но есть проблема. Вот как данные записались:
    Код (Text):
    1. [
    2.     {
    3.         "r030":643,"txt":"\u0420\u043e\u0441\u0456\u0439\u0441\u044c\u043a\u0438\u0439 \u0440\u0443\u0431\u043b\u044c","rate":0.408770000000000022222224060897133313119411468505859375,"cc":"RUB","exchangedate":"15.07.2019"
    4.     },
    5.     {
    6.         "r030":840,"txt":"\u0414\u043e\u043b\u0430\u0440 \u0421\u0428\u0410","rate":25.76058400000000148111212183721363544464111328125,"cc":"USD","exchangedate":"15.07.2019"
    7.     },
    8.     {
    9.         "r030":933,"txt":"\u0411i\u043b\u043e\u0440\u0443\u0441\u044c\u043a\u0438\u0439 \u0440\u0443\u0431\u043b\u044c","rate":12.663740000000000662794263917021453380584716796875,"cc":"BYN","exchangedate":"15.07.2019"
    10.     },
    11.     {
    12.         "r030":978,"txt":"\u0404\u0432\u0440\u043e","rate":28.98838500000000095724317361600697040557861328125,"cc":"EUR","exchangedate":"15.07.2019"
    13.     }
    14. ]
    Было в одну строку, я для читаемости сделал переносы и табы.
    При первом обновлении получается такой код. При следующих обновах опять всё стирается и записывается null

    Можно это как то исправить?
     
  4. master-web

    master-web Новичок

    С нами с:
    29 май 2019
    Сообщения:
    44
    Симпатии:
    16
    Вот, вполне рабочий код
    PHP:
    1. $json = @file_get_contents("https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json");
    2. if (!empty($json)) {
    3.     $kurs_new = json_decode($json);
    4.     $cron_curs = file_get_contents( __DIR__.'/kursNBU.json');
    5.     $kurs_old = json_decode($cron_curs);
    6.  
    7.     foreach ($kurs_new as $cur) {
    8.         foreach ($kurs_old as $item) {
    9.             if ($item->r030 == $cur->r030) {
    10.                 $item->rate = $cur->rate;
    11.                 $item->exchangedate = $cur->exchangedate;
    12.             }
    13.         }
    14.     }
    15.    
    16.     $json_new = json_encode($kurs_old);
    17.     file_put_contents(__DIR__.'/kursNBU.json', $json_new, LOCK_EX);
    18. }
     
    koresh нравится это.
  5. koresh

    koresh Новичок

    С нами с:
    11 июл 2019
    Сообщения:
    19
    Симпатии:
    0
    Спасибо! Поставил ваш код.

    Для теста json отредактировал так:
    Код (Text):
    1. [
    2.     {
    3.         "r030":643,"txt":"Російський рубль","rate":1,"cc":"RUB","exchangedate":"15.07.2017"
    4.     },
    5.     {
    6.         "r030":840,"txt":"Долар США","rate":1,"cc":"USD","exchangedate":"15.07.2017"
    7.     },
    8.     {
    9.         "r030":933,"txt":"Бiлоруський рубль","rate":1,"cc":"BYN","exchangedate":"15.07.2017"
    10.     },
    11.     {
    12.         "r030":978,"txt":"Євро","rate":1,"cc":"EUR","exchangedate":"15.07.2017"
    13.     }
    14. ]
    После запуска задачи вот что получилось:
    Код (Text):
    1. [{"r030":643,"txt":"\u0420\u043e\u0441\u0456\u0439\u0441\u044c\u043a\u0438\u0439 \u0440\u0443\u0431\u043b\u044c","rate":0.408770000000000022222224060897133313119411468505859375,"cc":"RUB","exchangedate":"15.07.2019"},{"r030":840,"txt":"\u0414\u043e\u043b\u0430\u0440 \u0421\u0428\u0410","rate":25.76058400000000148111212183721363544464111328125,"cc":"USD","exchangedate":"15.07.2019"},{"r030":933,"txt":"\u0411i\u043b\u043e\u0440\u0443\u0441\u044c\u043a\u0438\u0439 \u0440\u0443\u0431\u043b\u044c","rate":12.663740000000000662794263917021453380584716796875,"cc":"BYN","exchangedate":"15.07.2019"},{"r030":978,"txt":"\u0404\u0432\u0440\u043e","rate":28.98838500000000095724317361600697040557861328125,"cc":"EUR","exchangedate":"15.07.2019"}]
    Ломаются значения для ключей "txt" и что самое важное, для "rate".
    Так как "txt" в скрипте не трогается, то наверное где то в процессе кодирования-декодирования такое вылазит.

    Почему так? Есть ли рецепт как такое вылечить?
     
  6. master-web

    master-web Новичок

    С нами с:
    29 май 2019
    Сообщения:
    44
    Симпатии:
    16
    В самом начале скрипта укажите кодировку
    PHP:
    1. header('Content-Type: text/html; charset=UTF-8');
    и замените строку
    PHP:
    1. $json_new = json_encode($kurs_old, JSON_UNESCAPED_UNICODE);
    rate у меня записывается корректно. Я так понимаю, что данная проблема связана со значением serialize_precision в конфигах https://www.php.net/manual/ru/function.json-encode.php
    Как вариант, можете просто приводить rate к строковому типу
    PHP:
    1. $item->rate = (string) $cur->rate;
     
    koresh нравится это.
  7. TeslaFeo

    TeslaFeo Старожил

    С нами с:
    9 мар 2016
    Сообщения:
    2.989
    Симпатии:
    759
    ничего там не ломается
    если прочитаете этот файл и сделаете json_decode, то всё будет ок.
     
  8. koresh

    koresh Новичок

    С нами с:
    11 июл 2019
    Сообщения:
    19
    Симпатии:
    0
    Спасибо! Ваш рецепт помог. Теперь значение в ключе "txt" правильное, а значение ключа "rate" стало строковым типом данных, но само значение правильное.

    Подскажите пожалуйста, а может это быть связано с настройкой php на хостинге?
    Я смотрю, у меня на хостинге в разделе php есть вот такая настройка:
    screenshot-2019.07.13-09-59-29.jpg

    Это оно?
     
  9. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    @koresh, это не то что не оно, это совсем не рядом.
     
    koresh нравится это.
  10. koresh

    koresh Новичок

    С нами с:
    11 июл 2019
    Сообщения:
    19
    Симпатии:
    0
    У меня в настройках хостинга есть раздел "Настройка сайта". Там указана кодировка UTF-8.

    Убрал из скрипта:
    PHP:
    1. header('Content-Type: text/html; charset=UTF-8');
    Задача отрабатывает не ломая значения ключа "txt"

    Эту часть рецепта решения проблемы оставил:
    PHP:
    1. $json_new = json_encode($kurs_old, JSON_UNESCAPED_UNICODE);
    и
    Код (Text):
    1. $item->rate = (string) $cur->rate;