fastjson:对于Exception中复杂类型(enum,...以及自定义类型)成员的处理

如果一个Exception类中有枚举类型或其他复杂类型(比如java.util.Date,或自定义类型)的成员,fastjson反序列化会抛出异常。

	// ServiceSecurityException 类型中 type 成员是个枚举类型SecurityExceptionType
	ServiceSecurityException exp = new ServiceSecurityException("hello").setType(SecurityExceptionType.INVALID_PERSON_ID).setDeviceID(10);
	// 序列化可以正常输出
	System.out.println(JSON.toJSONString(exp));
	// 反序列化就会抛出异常
	JSON.parseObject(JSON.toJSONString(exp), ServiceSecurityException.class);

抛出的异常如下:

com.alibaba.fastjson.JSONException: set property error, type
at com.alibaba.fastjson.parser.deserializer.FieldDeserializer.setValue(FieldDeserializer.java:136)
at com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer.deserialze(ThrowableDeserializer.java:132)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:626)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:348)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:252)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:471)
at net.gdface.facelog.CloneTest.test(CloneTest.java:56)

这应该是个bug,(我用版本的是1.2.38,就是支持java7的最后一个版本,再往后的版本都是java8编译的).跟踪了fastjson的源码,发现用于Exception的反序列化的ThrowableDeserializer代码中对于自定义成员反序列化的逻辑处理过于简单,只考虑了简单数据类型。
看了最新版本1.2.41对应代码,发现这个bug在1.2.41已经解决了,但1.2.41是java8编译的,因为我的项目编译对java版本的要求是java7,所以不能使用。所以这个问题,还得自己想办法解决。

我解决方法是绕开它,因为是在ThrowableDeserializer这里的代码出了问题,所以不能让fastjson以ThrowableDeserializer来实现 序列化和反序列化。

#步骤1–序列化过程
将异常类型中需要序列化的字段序列化成一个简单的json string,这样在反序列化时fastjson就不会把它当做一个异常类型交给ThrowableDeserializer来处理。

	public String toJsonString(ServiceSecurityException exp){
		HashMap<String,Object> fields = new HashMap<String,Object>();
		fields.put("type", exp.getType());
		fields.put("deviceID", exp.getDeviceID());
		return JSON.toJSONString(fields);
	}

#步骤2–反序列化
JSON.parseObject方法将上一步的json string 反序列化成一个JSONObject对象,
#步骤3–反序列化
TypeUtils.castToJavaBean将上一步的JSONObject对象转换为指定的异常类型

代码实现如下:

String jsonStr = toJsonString(exp);
JSONObject obj = JSON.parseObject(jsonStr);
ServiceSecurityException newExp = TypeUtils.castToJavaBean(obj, ServiceSecurityException.class);
加载配置: 30 个参数,版本: 1753923417797 配置更新广播: v1753923417797 (30项) Exception in thread "main" org.apache.flink.runtime.client.JobExecutionException: Job execution failed. at org.apache.flink.runtime.jobmaster.JobResult.toJobExecutionResult(JobResult.java:144) at org.apache.flink.runtime.minicluster.MiniClusterJobClient.lambda$getJobExecutionResult$3(MiniClusterJobClient.java:137) at java.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:602) at java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577) at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962) at org.apache.flink.runtime.rpc.akka.AkkaInvocationHandler.lambda$invokeRpc$0(AkkaInvocationHandler.java:237) at java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:760) at java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:736) at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962) at org.apache.flink.runtime.concurrent.FutureUtils$1.onComplete(FutureUtils.java:1081) at akka.dispatch.OnComplete.internal(Future.scala:264) at akka.dispatch.OnComplete.internal(Future.scala:261) at akka.dispatch.japi$CallbackBridge.apply(Future.scala:191) at akka.dispatch.japi$CallbackBridge.apply(Future.scala:188) at scala.concurrent.impl.CallbackRunnable.run$$$capture(Promise.scala:60) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala) at org.apache.flink.runtime.concurrent.Executors$DirectExecutionContext.execute(Executors.java:73) at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:68) at scala.concurrent.impl.Promise$DefaultPromise.$anonfun$tryComplete$1(Promise.scala:284) at scala.concurrent.impl.Promise$DefaultPromise.$anonfun$tryComplete$1$adapted(Promise.scala:284) at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:284) at akka.pattern.PromiseActorRef.$bang(AskSupport.scala:573) at akka.pattern.PipeToSupport$PipeableFuture$$anonfun$pipeTo$1.applyOrElse(PipeToSupport.scala:22) at akka.pattern.PipeToSupport$PipeableFuture$$anonfun$pipeTo$1.applyOrElse(PipeToSupport.scala:21) at scala.concurrent.Future.$anonfun$andThen$1(Future.scala:532) at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:29) at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:29) at scala.concurrent.impl.CallbackRunnable.run$$$capture(Promise.scala:60) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala) at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55) at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:91) at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12) at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:81) at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:91) at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40) at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:44) at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) Caused by: org.apache.flink.runtime.JobException: Recovery is suppressed by NoRestartBackoffTimeStrategy at org.apache.flink.runtime.executiongraph.failover.flip1.ExecutionFailureHandler.handleFailure(ExecutionFailureHandler.java:138) at org.apache.flink.runtime.executiongraph.failover.flip1.ExecutionFailureHandler.getFailureHandlingResult(ExecutionFailureHandler.java:82) at org.apache.flink.runtime.scheduler.DefaultScheduler.handleTaskFailure(DefaultScheduler.java:216) at org.apache.flink.runtime.scheduler.DefaultScheduler.maybeHandleTaskFailure(DefaultScheduler.java:206) at org.apache.flink.runtime.scheduler.DefaultScheduler.updateTaskExecutionStateInternal(DefaultScheduler.java:197) at org.apache.flink.runtime.scheduler.SchedulerBase.updateTaskExecutionState(SchedulerBase.java:682) at org.apache.flink.runtime.scheduler.SchedulerNG.updateTaskExecutionState(SchedulerNG.java:79) at org.apache.flink.runtime.jobmaster.JobMaster.updateTaskExecutionState(JobMaster.java:435) at sun.reflect.GeneratedMethodAccessor19.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.flink.runtime.rpc.akka.AkkaRpcActor.handleRpcInvocation(AkkaRpcActor.java:305) at org.apache.flink.runtime.rpc.akka.AkkaRpcActor.handleRpcMessage(AkkaRpcActor.java:212) at org.apache.flink.runtime.rpc.akka.FencedAkkaRpcActor.handleRpcMessage(FencedAkkaRpcActor.java:77) at org.apache.flink.runtime.rpc.akka.AkkaRpcActor.handleMessage(AkkaRpcActor.java:158) at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:26) at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:21) at scala.PartialFunction.applyOrElse(PartialFunction.scala:123) at scala.PartialFunction.applyOrElse$(PartialFunction.scala:122) at akka.japi.pf.UnitCaseStatement.applyOrElse(CaseStatements.scala:21) at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:171) at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:172) at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:172) at akka.actor.Actor.aroundReceive(Actor.scala:517) at akka.actor.Actor.aroundReceive$(Actor.scala:515) at akka.actor.AbstractActor.aroundReceive(AbstractActor.scala:225) at akka.actor.ActorCell.receiveMessage$$$capture(ActorCell.scala:592) at akka.actor.ActorCell.receiveMessage(ActorCell.scala) at akka.actor.ActorCell.invoke(ActorCell.scala:561) at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:258) at akka.dispatch.Mailbox.run(Mailbox.scala:225) at akka.dispatch.Mailbox.exec(Mailbox.scala:235) ... 4 more Caused by: com.esotericsoftware.kryo.KryoException: java.lang.UnsupportedOperationException Serialization trace: allEncodes (com.tongchuang.realtime.mds.ULEDataanomalyanalysis$ConfigBundle) at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:125) at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528) at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:761) at org.apache.flink.api.java.typeutils.runtime.kryo.KryoSerializer.deserialize(KryoSerializer.java:354) at org.apache.flink.streaming.runtime.streamrecord.StreamElementSerializer.deserialize(StreamElementSerializer.java:193) at org.apache.flink.streaming.runtime.streamrecord.StreamElementSerializer.deserialize(StreamElementSerializer.java:46) at org.apache.flink.runtime.plugable.NonReusingDeserializationDelegate.read(NonReusingDeserializationDelegate.java:53) at org.apache.flink.runtime.io.network.api.serialization.NonSpanningWrapper.readInto(NonSpanningWrapper.java:337) at org.apache.flink.runtime.io.network.api.serialization.SpillingAdaptiveSpanningRecordDeserializer.readNonSpanningRecord(SpillingAdaptiveSpanningRecordDeserializer.java:128) at org.apache.flink.runtime.io.network.api.serialization.SpillingAdaptiveSpanningRecordDeserializer.readNextRecord(SpillingAdaptiveSpanningRecordDeserializer.java:103) at org.apache.flink.runtime.io.network.api.serialization.SpillingAdaptiveSpanningRecordDeserializer.getNextRecord(SpillingAdaptiveSpanningRecordDeserializer.java:93) at org.apache.flink.streaming.runtime.io.AbstractStreamTaskNetworkInput.emitNext(AbstractStreamTaskNetworkInput.java:95) at org.apache.flink.streaming.runtime.io.StreamOneInputProcessor.processInput(StreamOneInputProcessor.java:66) at org.apache.flink.streaming.runtime.io.StreamTwoInputProcessor.processInput(StreamTwoInputProcessor.java:98) at org.apache.flink.streaming.runtime.tasks.StreamTask.processInput(StreamTask.java:423) at org.apache.flink.streaming.runtime.tasks.mailbox.MailboxProcessor.runMailboxLoop(MailboxProcessor.java:204) at org.apache.flink.streaming.runtime.tasks.StreamTask.runMailboxLoop(StreamTask.java:684) at org.apache.flink.streaming.runtime.tasks.StreamTask.executeInvoke(StreamTask.java:639) at org.apache.flink.streaming.runtime.tasks.StreamTask.runWithCleanUpOnFail(StreamTask.java:650) at org.apache.flink.streaming.runtime.tasks.StreamTask.invoke(StreamTask.java:623) at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:779) at org.apache.flink.runtime.taskmanager.Task.run(Task.java:566) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055) at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:109) at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:22) at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:679) at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:106) ... 22 more
08-01
### 关于 `com.alibaba.fast2:fast2:jar:1.2.83` 的问题分析 在 Maven 中央仓库或其他常见公共存储库中,目前并未发现名为 `com.alibaba.fast2:fast2:jar:1.2.83` 的依赖项。这可能是因为该依赖项不存在、拼写错误或者是一个内部项目专用的依赖。 以下是针对此问题的具体解决方案: #### 1. **确认依赖名称** 如果存在拼写错误的可能性,则应重新核对实际所需的依赖名称及其坐标(groupId 和 artifactId)。例如,常见的 Alibaba JSON 库通常命名为 `com.alibaba:fastjson` 而不是 `com.alibaba.fast2:fast2`[^1]。 #### 2. **检查本地或私有仓库** 某些企业会开发并维护自己的私有 Maven 仓库,用于托管自定义构建的 JAR 文件。在这种情况下,需确保项目的 `pom.xml` 或者 `settings.xml` 配置文件已正确配置指向这些私有仓库地址。例如,在 `pom.xml` 中添加如下片段以指定额外的远程仓库位置: ```xml <repositories> <repository> <id>private-repo</id> <url>http://your-private-maven-repository.com/repo</url> </repository> </repositories> ``` #### 3. **手动引入外部 JAR** 当无法通过标准方式获取所需依赖时,可以选择将其作为第三方资源导入到工程中。具体操作方法包括但不限于以下两种途径之一: - 将目标 jar 文件放置至项目的 lib 目录下并通过 IDE 设置加载路径; - 使用命令行工具 mvn install 手动安装到本地 maven 缓存区。执行样例脚本如下所示: ```bash mvn install:install-file \ -Dfile=/path/to/your/custom-fast2-jar-version.jar \ -DgroupId=com.alibaba.fast2 \ -DartifactId=fast2 \ -Dversion=1.2.83 \ -Dpackaging=jar ``` #### 4. **处理 fastjson 特定异常** 对于提到的 JSONException (`unclosed string`) 错误消息以及建议采用 Apache Commons Lang 提供的方法 StringEscapeUtils.unescapeJavaScript 来预处理输入数据的情况,这是为了规避因转义字符引起解析失败的风险。尽管如此,仍推荐优先更新至最新稳定版 FastJSON 库以便利用官方修复后的功能改进成果[^2]。 另外值得注意的是,上述属性设置代码展示了如何动态修改 Properties 对象内的键值对内容[^3]。虽然这段逻辑本身与当前讨论主题无直接关联,但它体现了 Java 平台下灵活管理配置参数的一种典型实践模式。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值