2016-03-17 4 views
4

Я пытаюсь передать структуру через функцию, но целые числа в ней преобразуются в научную нотацию.Длинные целые числа преобразуются в научную нотацию - ColdFusion

Перед десериализации:

{"businessUnitValidList":2003051509034372557922 
    , "shortMessage":"Success" 
    , "longMessage":"Request Completed Successfully." 
    , "status":20001 
} 

После десериализации:

businessUnitValidList 2.00305150903E+021 

Я попытался преобразовать его в строку, но она по-прежнему дает мне тот же результат. Есть идеи?

Примечание: Если у меня есть более одного значения в моем businessUnitValidList, цифры отображаются так, как они должны.

EDIT

Это текущий код итерации:

<cfloop array="#businessUnitArray#" index="i"> 

    <cfquery name="validatebusinessUnit" datasource="dbproduction"> 
     select doctorid from survey.dbo.clientLocationMap 
     where clientbrandid = '#arguments.clientBrandid#' 
     and clientLocation = '#i#' 
    </cfquery> 

    <cfif validatebusinessUnit.recordcount gt 0> 
     <cfset businessUnitValidList = listAppend(businessUnitValidList,toString(validatebusinessUnit.doctorid),",")> 
    <cfelse> 
     <cfset businessUnitInValidList = listAppend(businessUnitInValidList,i,",")> 
    </cfif> 

</cfloop> 

<cfif businessUnitInValidList neq ''> 
    <cfset ResponseStruct['BusinessUnitCodes']['businessUnitMixResponse']['businessUnitInValidList'] = "#businessUnitInValidList#"> 
    <cfset ResponseStruct['BusinessUnitCodes']['businessUnitMixResponse']['businessUnitValidList'] = "#businessUnitValidList#"> 
    <cfreturn serializeJSON(ResponseStruct['BusinessUnitCodes']['businessUnitMixResponse'])> 
<cfelse> 
    <cfset ResponseStruct['BusinessUnitCodes']['businessUnitSuccess']['businessUnitValidList'] = "#businessUnitValidList#"> 
    <cfreturn serializeJSON(ResponseStruct['BusinessUnitCodes']['businessUnitSuccess'])> 
</cfif> 
+1

Как мы должны помочь вам, если вы не предоставили код, который имеет эту проблему? Вы были здесь достаточно долго, чтобы знать, как задавать соответствующие вопросы - [mcve] –

+4

Попробуйте преобразовать его в строку и включить ведущее пространство; например «businessUnitValidList»: «2003051509034372557922» –

+0

Вы также можете попробовать использовать функцию 'PrecisionEvaluate()' на нем - http://stackoverflow.com/a/16968077/1636917 –

ответ

3

(слишком долго для комментариев)

мой код производит правильный результат является deserializeJSON(), что вызывает проблему.

Не совсем. Значение JSON верное, но сериализация не содержит окружающих котировок. Это означает, что значение будет обрабатываться как числовой тип во время десериализации, что вызовет проблему, которую вы наблюдаете.Если вы не можете принудительно выполнить сериализацию для обработки значения как строки, десериализованный результат всегда будет неправильным. Как Carl Von Stetten already mentioned, это ошибка. Ответ Jedihomer Townend appending a space character, вероятно, является самым простым обходом.

Более длинный ответ:

Несмотря на улучшение обработки JSON CF11, в CF еще немного слишком «полезно» ... Как вы отметили, CF определяет значение числовой при сериализации и опускает окружающие кавычки , Следовательно, обозначение типа значения как числовое.

Это звучит здорово, пока вы не попытаетесь десериализовать. Если значение было заключено в кавычки, оно будет обрабатываться как строка, а исходное значение будет сохранено. К сожалению, без кавычек считается числовыми, что означает CF должны набивать значение в one of its two numeric data types:

  1. Real или число с плавающей точкой, т.е. java.lang.Double или
  2. 32-битное целое, т.е. java.lang.Integer

maximum value of an Integer - 2147483647. Очевидно, ваш номер слишком большой для этого, поэтому CF конвертирует его в java.lang.Double. Это проблема по двум причинам. Во-первых, Double - это approximate type. Во-вторых, согласно правилам этого класса, scientific notation may be used when representing the number as a String, т.е. когда переменная отображается с помощью cfoutput или cfdump. Вот почему десериализованный результат выглядит иначе, чем ожидалось. Если вы не можете заставить его обрабатывать строку при сериализации, результат десериализации всегда будет неправильным.

Справедливости ради, CF11 содержит ряд улучшений для обработки JSON. К сожалению, большинство из них вращаются вокруг объектов cfc и query. Учитывая вашу текущую структуру, она не будет довольно работы. Однако, если вы смогли использовать объект запроса , вы можете решить проблему с помощью нового уровня приложения this.serialization.serializeQueryAs = "struct";. Это заставляет более разумный формат для сериализованных запросов, чем в более ранних версиях. Поскольку CF11 относится к типам данных столбцов при сериализации, значение сохраняется, если тип данных столбца BIGDECIMAL, или вы передаете его как VARCHAR. К сожалению, CF все еще содержит имена столбцов запроса, но базовые значения сохраняются.

Результат:

[ { "BUSINESSUNITVALIDLIST" : "2003051509034372557922", 
    "LONGMESSAGE" : "Request Completed Successfully.", 
    "SHORTMESSAGE" : "Success", 
    "STATUS" : 20001 
    } ] 

Код:

qry = queryNew(""); 
queryAddColumn(qry, "businessUnitValidList", "varchar", ["2003051509034372557922"]); 
queryAddColumn(qry, "shortMessage", "varchar", ["Success"]); 
queryAddColumn(qry, "longMessage", "varchar", ["Request Completed Successfully."]); 
queryAddColumn(qry, "status", "integer", [20001]); 

json = serializeJSON(qry); 
writeDump(deserializeJSON(json)); 

CF11 также введены пользовательские сериализаторы/deserializers, которые мощь работа здесь. Хотя это, вероятно, слишком велико для этой конкретной задачи.

Сказав все это, простейшим вариантом является использование «добавления нечислового символа». Что ж ..Либо так, либо перейти в пользовательскую библиотеку, которая может сделать более последовательную работу с обработкой JSON ;-)

Side Примечание/Эффективность:

Если нет особых причин, вы должны выполнить запрос в в цикле есть более эффективные варианты (специфичные для dbms, о которых вы не упомянули). Кроме того, не забудьте использовать cfqueryparam для всех переменных параметров запроса. Среди многих преимуществ - повышение производительности, когда один и тот же запрос выполняется несколько раз - например, внутри цикла.

6

JSON сериализация ColdFusion имеет проблемы и может варьироваться в зависимости от версии и даже исправлений. Как упоминал Jedihomer Townend в комментариях, ведущее пространство должно заставить CF обрабатывать его струной, а не бросать ее.

Я только что попробовал это на CF10, 11 и 2016 и сохранил вход.

<cfscript> 
a = { 
    "businessUnitValidList":" 2003051509034372557922", 
    "shortMessage":"Success", 
    "longMessage":"Request Completed Successfully.", 
    "status":20001 
}; 
json = serializeJSON(a); 
b = deserializeJSON(json); 

writeDump(b); 
</cfscript> 

Вы можете попробовать его здесь:

http://trycf.com/gist/70b86fbb57f752125f35/acf?theme=monokai

+0

Я вижу, что у вас есть пробел перед номером, и он преобразуется в строку. Когда я это делаю, у меня нет проблем. Проблема заключается в том, что '' businessUnitValidList ":' 2003051509034372557922 ",' подобен этому '" businessUnitValidList ": 2003051509034372557922,' – Geo

+1

Да, это потому, что число слишком велико для ColdFusion, чтобы справиться с ним, поэтому оно преобразует его в научную нотацию. Заставляя его рассматривать его как строку, он не преобразует его - это трюк/хак, но это единственный вариант, который, как я думаю, у вас здесь. –

3

В Java есть тип данных BigInteger для хранения больших значений. В Coldfusion мы можем использовать с помощью JavaCast целое число, длинное и двойное. Но проблема в том, что даже с «длинным» типом данных можно хранить только 19 цифр.

И путем преобразования числа в строку может быть проблематичным выполнение математических операций. Здесь мы можем использовать precisionEvaluate() при выполнении математических операций.

Функция PrecisionEvaluate позволяет вычислять произвольно большие десятичные значения (значения BigDecimal precision). Арифметика BigDecimal precision принимает и генерирует десятичные числа любой длины.

В этом примере вы можете использовать, как это:

<cfset ResponseStruct['BusinessUnitCodes']['businessUnitMixResponse']['businessUnitInValidList'] = "#precisionEvaluate(businessUnitInValidList)#">

+0

* Преобразование числа в строку может быть проблематичным для выполнения математических операций * Правда, но представление JSON должно быть строкой. В противном случае, когда десериализация CF преобразует его в один из двух числовых типов данных: 32-битное целое (слишком маленькое) или двойное (вызывает научную нотацию). Даже если вы используете метод precisionEvaluate по пути. – Leigh

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