LINUX.ORG.RU

Вопрос по типам данных JSON

 


0

1

Столкнулся тут с необходимостью чтения JSON, и возникли вопросы о числовых типах данных. Вот есть в спеке какой-то integer и numeric. А откуда читающей программе знать, какой длинны и формата эти числа? Ведь целое может быть самой разной длины (плюс знака), а числа с плавающей точкой могут быть как минимум одинарной или двойной точности. Как это всё специфицируется в документе JSON?

★★★★★

Последнее исправление: seiken (всего исправлений: 1)

Как это всё специфицируется в документе JSON?

Правильный вопрос, наверное, «как это всё специфицируется в JavaScript?».

vvn_black ★★★★★
()
Ответ на: комментарий от vvn_black

Правильный вопрос, наверное, «как это всё специфицируется в JavaScript?»

Да, подозревал, что это формат для одного языка.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

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

Partisan ★★★★
()
JSON is agnostic about the semantics of numbers. In any programming language, there can be a variety of
number types of various capacities and complements, fixed or floating, binary or decimal. That can make
interchange between different programming languages difficult. JSON instead offers only the representation of
numbers that humans use: a sequence of digits. All programming languages know how to make sense of digit
sequences even if they disagree on internal representations. That is enough to allow interchange.

ECMA 404

deadNightTiger ★★★★★
()
Ответ на: комментарий от deadNightTiger

JSON instead offers only the representation of numbers that humans use: a sequence of digits.

Люди не только разряды используют, но и всякие символы типа Е для записи в экспоненциальном формате или «0x» для обозначения 16-ричной системы, а ещё можно использовать запятую вместо точки. Так что то, что используют люди - это вовсе не только «sequence of digits». Такое впечатление, что спеку составляли гуманитарии.

seiken ★★★★★
() автор топика
Последнее исправление: seiken (всего исправлений: 1)
Ответ на: комментарий от seiken

Парсь дробные в зависимости от кол-ва разрядов (символов) в float или double

И вообще ты странный — язык сообщи, поди либа готовая доступна.

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Ну либы-то есть, конечно. Просто если спека явно не прописывает, какой формат должен быть у чисел, это значит, что для одного и того же документа один валидатор может сказать «ОК», а другой - «говно». И вот ты такой проверяешь присланный по сети JSON, и твой валидатор на C++ говорит «говно», а валидатор того, кто документ посылает, на JS и говорит «ОК». И аргумент в пользу правоты того валидатора на JS будет «это же супер-пупер валидатор, который полвеба использует», а не «вот тут в вашем C++ валидаторе бага, потому что вот такой-то конкретный пример записи числа валиден и означает то-то и сё-то».

seiken ★★★★★
() автор топика

Ну или та же спека, только «разжевано»

https://www.tutorialspoint.com/json/json_data_types.htm

Но лучше подсмотреть в готовой библиотеке - пример от «горячих финских парней» я привёл выше, поскольку сам сижу сейчас на «Ваадине».

Bioreactor ★★★★★
()

В JSON (как и в JS) есть просто числа, без разделения на integer / float / double. Поэтому «читающая программа» должна просто проверить синтаксис.

Когда дело доходит до хранения и обработки JSON-чисел, то все несколько сложнее. Во всех реализациях сейчас один из двух вариантов:

  • union {int64; double} плюс явный признак «integer или double».
  • хранение int внутри double в денормализованном виде с ограничением 2^52 на модуль значения, т.е. как в lua.
Deleted
()
Ответ на: комментарий от Deleted

В JSON
int64
с ограничением 2^52 на модуль значения

Поэтому передаю числа как строки, 64 биты надо быдо делать, а не 52!

anonymous
()

Ниоткуда, это ж JSON, а не кошерный XML. Схемы нет, нихрена нет. Как договоришься со второй стороной, так и парсишь. Если не с кем договариваться, то сочувствую.

Deleted
()

Столкнулся тут с необходимостью чтения JSON,

А вы что пишите? Еще одну универсальную библиотеку для работы с JSON или таки прикладную задачу, где не «говно», скажем, это только целые числа от 0 до 999?

vodz ★★★★★
()
Ответ на: комментарий от anonymous

В JSON int64 с ограничением 2^52 на модуль значения

Поэтому передаю числа как строки, 64 биты надо быдо делать, а не 52!

52 там не потому что «надо/ненадо», а потому что таков размер мантиссы в 64-битных ieee754, т.е. целочисленный значения больше чем 2^52-1 не возможно засунуть в double без потери точности.

Избавление от этого ограничения требует хотя-бы одного бита, чтобы отличать любое int64 от любого double, когда это просто 8-байт в памяти. Тут тоже есть варианты:

  • выделять по 16 байт (12 на 32-битных платформах).
  • использовать тегированные указатели.
  • паковать в 9 байт.

Короче, внешнее удобство JSON внутри оборачивается слоями костылей. С другой стороны, это легко обойти, если не натягивать сову на глобус полностью, а просто читать из JSON данные в нужные «читающей программе» типы. Альтенативы = BJSON, MsgPack, fptu.

Deleted
()
Ответ на: комментарий от Deleted

Альтенативы = BJSON, MsgPack, fptu.

Пардон, libfptu.

Deleted
()
Ответ на: комментарий от vodz

а как звучит, столкнулся с необходимостью чтения, уже пишу кандидатскую

trashymichael ★★★
()
Ответ на: комментарий от poe

Есть transit с более строгой спецификацией.

Он какой-то странный мягко говоря, ни 2 ни полтора:

  • человеку читать уже неудобно, машине еще не удобно.
  • требует подходящего формата «нижнего уровня» (т.е. не самостоятельный).
  • схемы нет, IDL нет, валидация в виде exception при чтении.

В итоге как кактус для салата - не отравишься, но и есть не захочешь.

Deleted
()

Вопрос интерпретации типа данных на совести принимающей стороны. Теоретически (как это нередко бывает) вообще передаётся строка вида

"my_number":"10.0"

а ты понимай это так как следует из логики приложения.

Хотя, конечно, передавать числа в таком виде - скотство со стороны передающей стороны.

r_asian ★☆☆
()
Ответ на: комментарий от vvn_black

Правильный вопрос, наверное, «как это всё специфицируется в JavaScript?».
В JavaScript, Number - числовой тип данных в формате 64-битного числа двойной точности с плавающей запятой. В других языках программирования может существовать несколько чиловых типов данных, например: Integer, Float, Double или Bignum.

Это что, получается, в JS нет integer? Все арифметические вычисления в double float?

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

Это что, получается, в JS нет integer?

Есть bigint

Все арифметические вычисления в double float?

По большей части да.

crutch_master ★★★★★
()
Ответ на: комментарий от seiken

Это что, получается, в JS нет integer? Все арифметические вычисления в double float?

В JS есть тип «number», который ведет себя как integer если не засовывать в него ничего кроме целых, и как double в остальных случаях.

При этом также не гарантируется способность хранить большие чиселки. На практике (т.е. во всех актуальных реализациях) можно безопасно работать со значениями до 2^52 по модулю. Причины описал выше.

Deleted
()
Ответ на: комментарий от Deleted

Скорее всего он ведёт себя так.

Вот мой простенький пример-импровизация

package hello;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class Test1{
    
    public static void main(String[] args) {

        String str = String.format("{\"pi\":3.14}");
        JsonObject asJsonObject = new JsonParser().parse(str).getAsJsonObject();
        
        // неопределенность
        Object o = asJsonObject.get("pi").getAsNumber();
        System.out.printf("%s %s\n", o, o.getClass());
        o = asJsonObject.get("pi").getAsInt();
        System.out.printf("%s %s\n", o, o.getClass());
        o = asJsonObject.get("pi").getAsFloat();
        System.out.printf("%s %s\n", o, o.getClass());

        
        // по спеке пишем собственный обработчик
        if (asJsonObject.get("pi").getAsString().contains(".")) {  // и т.п.
            System.out.println(asJsonObject.get("pi").getAsFloat());
        } else {
            System.out.println(asJsonObject.get("pi").getAsInt());
        }
    }
}

$ java Test1
3.14 class com.google.gson.internal.LazilyParsedNumber
3 class java.lang.Integer
3.14 class java.lang.Float
3.14

Так что маленькую библиотечку собственную за полчаса можно и самим набросать.

-------

А что по этому поводу скажет сам ЦАРЬ?

Bioreactor ★★★★★
()
Последнее исправление: Bioreactor (всего исправлений: 1)

Любопытной особенностью реализаций является хранение целых чисел во float.

Javascript integers are limited to about 2^53 (there are no integers; just IEEE floats).

В Qt тоже самое. Если будешь передавать достаточное большое число знаки обрежутся если не влезет в мантиссу.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.