java - Spring MVC:如何在反序列化包含重复对象定义的 JSON 字符串时创建对象的单个实例
问题描述
我想使用 Spring MVC 将包含重复定义的 JSON 字符串反序列化为 java 对象。要求是为这些重复定义创建一个对象的单个实例,而不是创建具有相同内容的重复对象。
示例类:
import java.io.Serializable;
public class Example implements Serializable {
private String a;
private String b;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
}
JSON字符串:
[
{
"a": "a",
"b": "b"
},
{
"a": "a",
"b": "b"
},
{
"a": "a1",
"b": "b1"
}
]
我得到的输出:
ExampleList=[
Example@151c632a,
Example@5051613a,
Example@6212cffd
]
创建了三个单独的对象。
我想要的输出是:
ExampleList=[
Example@1eda78db,
Example@1eda78db,
Example@68a94d19
]
创建了 2 个对象(1eda78db 和 68a94d19)而不是 3 个。
我看到了一个类似的帖子,它需要实现readResolve()
,但是有没有什么简单的方法可以做到这一点,它的内存更少?
如何将两个 Java 序列化对象重新链接在一起?
这是我要解决的用例。对象accountT
和objId0
inaccountNameinfoTList
是一样的。我想修改对象accountT
并希望看到它反映在objId0
{
"accountT": {
"poidId0": 200,
"poidDb": 1,
"poidType": "/account",
"poidRev": 10
},
"accountNameinfoTList": [
{
"id": {
"recId": 1
},
"objId0": {
"poidId0": 200,
"poidDb": 1,
"poidType": "/account",
"poidRev": 10
},
"address": "2632 Marine Way",
"canonCompany": "child corp",
"canonCountry": "GB",
"city": "Elstree",
"company": "Child Corp"
}
]
}
解决方案
不确定这是否可以帮助其他人。我能够通过利用@JsonCreator
我创建了一个静态方法,createExample
通过使用传递值@ JsonProperty
public class Example implements Serializable {
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonValue
private String a;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonValue
private String b;
public Example() {
}
@JsonCreator
public static Example createExample(@JsonProperty("a") String a,
@JsonProperty("b") String b) {
Example example = new Example();
example.a = a;
example.b = b;
return (Example) ReferenceMap.findOriginalObject(example);
}
}
使用 ReferenceMap 保存 WeakHashMap 中的详细信息!
public class ReferenceMap {
public static final String KEY_WEAK_REFERENCE_MAP = "weakReferenceMap";
public static Object findOriginalObject(Object object) {
Map<Object, Reference<Object>> weakReferenceMap = fetchWeakReferenceMapFromServletRequest();
WeakReference<Object> originalReference = (WeakReference<Object>) weakReferenceMap.get(object);
Object originalObject = originalReference == null ? null : originalReference.get();
if (originalObject == null) {
originalObject = object;
weakReferenceMap.put(originalObject, new WeakReference<>(originalObject));
}
return originalObject;
}
private static Map<Object, Reference<Object>> fetchWeakReferenceMapFromServletRequest() {
HttpServletRequest
request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
Object requestAttribute = request.getAttribute(KEY_WEAK_REFERENCE_MAP);
if (requestAttribute == null) {
Map<Object, Reference<Object>> weakReferenceMap = new WeakHashMap<>();
requestAttribute = weakReferenceMap;
request.setAttribute(KEY_WEAK_REFERENCE_MAP, weakReferenceMap);
}
return (Map<Object, Reference<Object>>) requestAttribute;
}
}
有了这个,我确信总是得到一个现有的实例而不是创建一个新的实例。
更新 将 WeakHashMap 保存在 ServletRequestAttributes 而不是 JVM 的堆中。
推荐阅读
- mysql - 将列更改为 nullabe 的查询不起作用
- keras - Few questions about Keras documentation
- qlikview - after doing left join i am getting duplicate entries. Need to know how to remove duplicate entries
- docker - Docker 在 Azure devops 中构建和推送 git 代码
- javascript - Javascript 数组深拷贝未按预期工作
- r - R的任何方法可以提高R中停用词的执行速度?
- ios - ios13通知内容自定义高度
- azure - 如果配置了部署表单源控制,则无法从门户添加 WebJob
- php - 我无法上传文件
- vba - 将集合对象中的值分配给命名范围