在ActionScript 3中向SOAP Web服务传递“Null”(真实姓氏)的方法

在ActionScript 3中向SOAP Web服务传递“Null”(真实姓氏)的方法

技术背景

在使用ActionScript 3向SOAP Web服务传递数据时,可能会遇到传递“Null”(作为真实姓氏)这样的特殊字符串的问题。由于SOAP编码器对null值的处理存在一些潜在的错误,导致在传递特殊字符串时可能出现参数丢失或解析错误等情况。

实现步骤

追踪问题

最初以为是null被强制转换为字符串"null",且"null" == null的测试通过,但实际并非如此。通过在wonderfl.net上进行调试,并跟踪mx.rpc.xml.*中的代码,发现XMLEncoder类(3.5版本源代码中的第1795行)的setValue方法中,所有的XML编码最终归结为:

1
currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));

这本质上等同于:

1
currentChild.appendChild("null");

根据最初的调试,这段代码返回一个空的XML元素。

找出原因

根据Bug报告FLEX - 33664上评论者Justin Mclean的说法,以下代码是问题的根源:

1
2
3
4
5
var thisIsNotNull:XML = <root>null</root>;
if(thisIsNotNull == null){
// 总是会进入这里,因为(thisIsNotNull == null)奇怪地返回true
// 尽管thisIsNotNull是一个有效的XML类型实例
}

currentChild.appendChild接收到字符串"null"时,它首先将其转换为文本为null的根XML元素,然后将该元素与null字面量进行比较。这是一个弱相等性测试,因此包含null的XML可能被强制转换为null类型,或者null类型被强制转换为包含字符串"null"的根XML元素,导致本应失败的测试通过。

解决方案

  1. 使用CDATA值:对字段进行“null”检查,并将其转义为CDATA值。CDATA值是处理整个文本值的最合适方式,可以避免编码/解码问题。
  2. 修改XMLEncoder:修改mx.rpc.xml.XMLEncoder文件(Flex 4.5.1 SDK中的第121行):
1
2
if (content != null)
result += content;

需要扩展这个类以移除验证,然后修改SOAPEncoder使用修改后的XMLEncoder,修改Operation使用修改后的SOAPEncoder,最后修改WebService使用修改后的Operation类。
3. 使用RemoteObject/AMF:如果切换到使用RemoteObject/AMF与ColdFusion,null值可以正常传递。但在ColdFusion 10中,对象上具有null值的属性会从服务器端对象中移除,因此在访问属性之前需要检查属性是否存在。

1
2
3
4
5
<cfif (structKeyExists(arguments.myObject,'propertyName'))>
<!--- no property code ---&>
<cfelse>
<!--- handle property normally ---&>
</cfif>
  1. 客户端特殊处理:在客户端对'Null'字符串进行特殊处理,将其转换为不会出现的字符串,例如XXNULLXX,并在服务器端进行反向转换。
  2. 使用正式正确的null值传递方式:将null值作为<childtag2 xsi:nil="true" />传递。可以考虑在Apache Flex中修复这个问题,建议在Jira上提交问题或联系apache - flex邮件列表。
  3. 分割参数:如果SEARCHSTRING有最小长度要求,例如2个字符,可以将SEARCHSTRING参数从第二个字符处分割为两个参数SEARCHSTRING1 ("Nu")SEARCHSTRING2 ("ll"),在执行数据库查询时再将它们连接起来。

核心代码

测试字符串“null”与保留字null的关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="application1_initializeHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;

protected function application1_initializeHandler(event:FlexEvent):void
{
var s :String = "null";
if(s != null){
trace('null string is not equal to null reserved word using the != condition');
} else {
trace('null string is equal to null reserved word using the != condition');
}

if(s == null){
trace('null string is equal to null reserved word using the == condition');
} else {
trace('null string is not equal to null reserved word using the == condition');
}

if(s === null){
trace('null string is equal to null reserved word using the === condition');
} else {
trace('null string is not equal to null reserved word using the === condition');
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:Application>

最佳实践

  • 在进行XML编码时,优先使用严格相等性测试(===)来检查“nullness”。
  • 如果可能,尽量使用RemoteObject/AMF与ColdFusion进行通信,避免SOAP编码器的问题。
  • 在处理特殊字符串时,使用CDATA值或对其进行特殊处理,以避免编码/解码问题。

常见问题

  1. ColdFusion 10中null属性的处理:在ColdFusion 10中,对象上具有null值的属性会从服务器端对象中移除,需要在访问属性之前检查属性是否存在。
  2. SOAP编码器的序列化问题:Flex的SOAP编码器可能会错误地序列化null值,导致参数丢失或解析错误。可以通过修改相关类或使用其他通信方式来解决。

在ActionScript 3中向SOAP Web服务传递“Null”(真实姓氏)的方法
https://119291.xyz/posts/2025-05-09.passing-null-to-soap-web-service-in-actionscript3/
作者
ww
发布于
2025年5月9日
许可协议