2013-11-20 4 views
5

Использование go1.1.2 Win64, у меня есть программа Go, которая «marshal» представляет собой структуру, содержащую float64. Когда значение float64 не является целым числом, например. 1234.44, тогда он получает «маршал» как плавающий (json.Marshal). Однако, если это целое число, например. «1234.00» он сортируется как целое число «1234». Когда я получаю это на другом конце (Дарт), Дарт (30188) рассматривает целое число как целое число (на карте - JSON.decode). Следовательно, программа Дарт прерывается, когда представление данных с плавающей точкой (double) не содержит десятичной точки, и я пытаюсь «извлечь» ее из карты как двойной.Правильно ли идет маршал float64 в JSON?

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

Есть ли еще лучший способ справиться с этим, чем преобразовать float64 в integer?

ответ

5

JSON, как Javascript, не отличается между целыми числами и числами.

Если Dart обрабатывает 1234.00 по-разному от 1234, то он делает предположения о значении, которое не поддерживается JSON specification.

Хотя Go действительно маршалом правильно float64, один из способов обойти проблему с предположением Дарта является осуществление Marshaler interface на свой собственный тип:

type Number float64 

func (n Number) MarshalJSON() ([]byte, error) { 
    // There are probably better ways to do it. It is just an example 
    return []byte(fmt.Sprintf("%f", n)), nil 
} 

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

Рабочий пример на Playground

+0

Спасибо за решение. Я думаю, что это нужно решить на конце Дарта. Похоже, что целое число нельзя назначить двойнику в Дарте. Это кажется мне аномалией, но я согласен с тем, что я ошибаюсь, по крайней мере, с теоретической точки зрения (бросок, бросок и т. Д.). Решение, которое у меня есть, следующее: «double dAcctBal = (mAcctData ['D_AcctBal'] как num)/1;" (где mAcctData - это карта, где «D_AcctBal» может быть целым числом или двойным в зависимости от того, является ли оно целым числом). Это решение для меня выглядит немного взломанным, но если целое нельзя назначить двойнику напрямую? –

+0

Да, я согласен, что было бы лучше решить его на конце Дарта. Я также с радостью дам вам такое решение, если бы знал, но мой опыт с Дартом * очень * ограничен. Возможно, кто-то с большим количеством знаний может найти более идиоматическое решение Дарта. – ANisus

+0

JSON не указывает семантику его числовых литералов, поэтому более корректно использовать двойные числа, чем целые. Дарт имеет два типа номеров.Все, что содержит десятичную точку или экспоненциальную часть, должно быть двойным, а все остальное анализируется как целое число, которое в Dart обеспечивает большую точность, чем двойные. Это сохраняет как можно больше информации из номера JSON. Это требует, чтобы вы вручную использовали .toDouble, если хотите, чтобы все числа были удвоены. – lrn

1

Следующая по-видимому, (для меня) решения. Целочисленный метод toDouble() также работает с «num» (или наоборот). Мне кажется, что при работе с json и денежными значениями, которые Dart может интерпретировать как double или int, необходимо использовать «как num», а затем использовать встроенный метод toDouble().

Пример (Go):

type cuAcctRow struct { 
     ..... 
    D_AcctBal float64 
     ..... 
} 
    if baJsAcctDet, oOsError = json.Marshal(uAcctRow); oOsError != nil { 

Пример (Dart):

Map mAcctData = json.parse(sResponse); 

double dAcctBal = (mAcctData['D_AcctBal'] as num).toDouble(); 

Я не знаю, почему Дарт не допускает прямого назначения целого удвоить, но я Конечно, есть веская причина.

+0

Очень хорошая причина. Аннотации типа в Dart являются необязательными, и они рассматриваются как утверждения (они игнорируются в режиме производства). Это означает, что переменная не имеет типа, поэтому присвоение целого числа переменной, объявленной как double, должно работать одинаково, объявляется ли переменная double («double x») или просто динамической («var x»). Это предотвращает любое неявное преобразование. В проверенном режиме назначение назначается, и поскольку «int» не является подтипом «double», утверждение типа терпит неудачу. Вы должны сделать явное n.toDouble(). – lrn

+0

@lrn: Спасибо за объяснение. Я «должен» изучить это. Это меня озадачило, но я думаю, что есть несколько факторов. Пока я перешел от этого до сих пор, я полагаю, что мое маленькое «решение» в порядке. (как num) .toDouble() не очень обременительно, однако с практической точки зрения мне показалось странным, что int, который идеально совместим в диапазоне до double, не может быть напрямую привязан к двойнику. Как относительно просто, как эта небольшая проблема, есть несколько факторов (включая JS, я думаю, возможно, косвенно). –

Смежные вопросы