213 empty lists repesented as empty arrays (lib/field, lib/rest_api_helper, instance_operation_default)

This commit is contained in:
2026-03-12 14:59:15 +03:00
parent 5f995381df
commit 589b06bcc4
5 changed files with 25 additions and 9 deletions
+2 -2
View File
@@ -57,7 +57,7 @@
//variables.framework.docs={};
variables.framework.docs.APIName="svc-api";
variables.framework.docs.APIVersion="0.212"; /*$ git config --global --unset user.password*/
variables.framework.docs.APIVersion="0.213"; /*$ git config --global --unset user.password*/
variables.framework.globalHeaders = structNew();
variables.framework.globalHeaders["Access-Control-Expose-Headers"] = "Location";
@@ -427,7 +427,7 @@
<cfargument name="contragentUid"/>
<cfif !isValid('guid',arguments.usrUid)>
<cfthrow message="Invalid user uuid" detail="uuid=(#arguments.usrUid#) is not a valid UUID"/>
<cfthrow message="Invalid user uuid" detail="uuid=(#arguments.usrUid#) is not a valid UUID"/><!--- тут спорно, можно было бы и 400 и 500, но исключения из этой функции не дифференцированы по типам --->
</cfif>
<cfif !isValid('guid',arguments.contragentUid)>
<cfthrow message="Invalid contragent uuid" detail="uuid=(#arguments.contragentUid#) is not a valid UUID"/>
+2 -1
View File
@@ -4,6 +4,7 @@
<!---v0.4 добавлен атрибут container for json--->
<!---v0.5 добавлен атрибут type и трансляция в CF_SQL_--->
<!--- 20210326 v0.8 formatter --->
<!--- 20260312 v0.9 type="list" added as workaround--->
<cffunction name="passThrough"
returntype="any"
@@ -42,7 +43,7 @@
<cfargument name="type"/>
<cfswitch expression=#ARGUMENTS.type#>
<cfcase value="string">
<cfcase value="string,list">
<cfreturn "CF_SQL_VARCHAR"/>
</cfcase>
<cfcase value="integer">
+10 -1
View File
@@ -8,6 +8,7 @@
<!--- v0.05 2025-11-20 multiple field entries in filter, filter became array instead of structure--->
<!--- v0.06 2025-11-22 custom url parser used to prevent comma collision in lists--->
<!--- v0.06 2026-01-22 json-type field validation (isValidX)--->
<!--- v0.06 2026-03-12 empty2null off--->
<cffunction name="empty2null"
access="public"
@@ -56,6 +57,7 @@
<cfloop list=#structKeyList(ARGUMENTS.fieldMap)# index="local.col">
<cfset var obj=container/>
<cfset var formatter = structFind(ARGUMENTS.fieldMap[local.col], "formatter")/>
<cfset var type = structFind(ARGUMENTS.fieldMap[local.col], "type")/>
<cfif structKeyExists(ARGUMENTS.fieldMap[#local.col#],"container")>
<cfset var subContainerName = structFind(ARGUMENTS.fieldMap[local.col], "container")/>
@@ -68,7 +70,14 @@
</cfif>
<cfif queryColumnExists(ARGUMENTS.query, local.col)>
<cfset obj[ARGUMENTS.fieldNameDecorator(local.col)]=empty2null(formatter(ARGUMENTS.query[local.col][ARGUMENTS.query.currentRow]))/>
<cfif type EQ "list">
<!--- *** workaround for empty lists - keep them empty instead of null - should designate field type as list --->
<cfset obj[ARGUMENTS.fieldNameDecorator(local.col)]=formatter(ARGUMENTS.query[local.col][ARGUMENTS.query.currentRow])/>
<cfelse>
<cfset obj[ARGUMENTS.fieldNameDecorator(local.col)]=empty2null(formatter(ARGUMENTS.query[local.col][ARGUMENTS.query.currentRow]))/>
</cfif>
<!--- *** преобразование пустой строки в null преобразует в нулл также пустые списки, что искажает факт --->
</cfif>
<!---*** не уверен в надежности конструкции во всех реализациях CF, контекст query передастся ли--->
</cfloop>
@@ -840,7 +840,11 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
where s.svc_id=<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#arguments.svcId# null=#!isValid("integer", arguments.svcId)#/>
order by r.sort, r.resource_realm
</cfquery> <!--- <cfdump var=#arguments#/> cfdump здесь провоцирует NPE --->
<cfreturn valueList(local.qAvailableResourceRealm.resource_realm)/>
<cfif local.qAvailableResourceRealm.recordCount>
<cfreturn valueList(local.qAvailableResourceRealm.resource_realm)/>
<cfelse>
<cfreturn ""/><!--- иначе для пустого резалтсета генерируется null --->
</cfif>
</cffunction>
+6 -4
View File
@@ -75,11 +75,11 @@
<m:field>p.label</m:field>
<m:field>p.data_type</m:field>
<m:field>null as data_descriptor</m:field>
<m:field formatter=#function(x){return listToArray(x);}#>p.value_list</m:field>
<m:field formatter=#function(x){return listToArray(x);}# type="list">p.value_list</m:field>
<m:field <!--- formatter=#function(x){return listToArray(generateValueList(x));}# --->>p.func</m:field><!--- *** отчаявшись сделать красиво --->
<m:field>p.ref_svc_id</m:field>
<m:field formatter=#request.castToBool#>p.is_required</m:field>
<m:field>p.default_value</m:field><!--- can be overridden bu default_compute --->
<m:field>p.default_value</m:field><!--- can be overridden by default_compute --->
<m:field>p.default_compute</m:field>
<m:field>p.regex</m:field>
<m:field>p.unique_scope</m:field>
@@ -129,6 +129,7 @@
<cfif len(trim(local.qCfsParam.value_list)) AND listLen(local.qCfsParam.value_list) EQ 1>
<cfset local.qCfsParam.default_value=local.qCfsParam.value_list/><!--- *** не очень красиво перетирать query, но делаем это довольно часто --->
</cfif>
<!--- <cfdump var=#local.qCfsParam.value_list# abort=true/> --->
<cfelseif len(local.qCfsParam.nested_ref)><!--- *** спрашивается, зачем нам изгаляться и возвращать замыкание, когда нам нужен json --->
<!--- <cfset var fNestedRef = generateClosure(local.qCfsParam.nested_ref, local.qCfsParam.config)/> --->
<cfset var args = {
@@ -218,7 +219,8 @@
)/>
<cfset "out.svcOperation.cfsParams"=[]/>
<!--- подставляем значение из стейта, если оно там есть (некорректно, потому что в стейте RFS параметры) --->
<!--- подставляем значение из стейта, если оно там есть (некорректно, потому что в стейте RFS параметры) --->
<cfloop query=#local.qCfsParam#>
<cfset local.qCfsParam.default_value = computeDefault(local.qCfsParam.default_compute, local.qCfsParam.default_value, qSvcOperation.svc_id, arguments.usrId)/><!--- *** не очень хорошо модифицировать запрос --->
<cfif len(local.qCfsParam.default_value) EQ 0>
@@ -230,7 +232,7 @@
</cfif>
</cfif>
<cfset var rec = this.helper.appendRecord(structNew("linked"), "", local.cfsParamMap, local.qCfsParam, this.helper.snake2camel)/>
<!--- <cfdump var=#rec# abort=true/> --->
<cfset arrayAppend(out.svcOperation.cfsParams, rec)/>
</cfloop>