[英]Flexjson or Gson : Protect object references after object serialization
我使用flexjson
序列化列表。 序列化后,我打印对象hashcode()
然后检查对象是否相等。
问题,操作后对象参考正在更改。 我不要
我的代码;
String sameOfString="sameOfString";
List<Object> list=new ArrayList<Object>();
list.add(sameOfString);
list.add(sameOfString);
list.add("differentString");
for(Object str:list){
System.out.println(str.hashCode());
}
**System.out.println(list.get(0)==list.get(1));**
System.out.println(list.get(0)==list.get(2));
System.out.println("--");
String json= new JSONSerializer().exclude("*.class").deepSerialize(list);
List<String> listDeserilized = (List<String>) new JSONDeserializer().deserialize(json);
for(Object str:listDeserilized){
System.out.println(str.hashCode());
}
**System.out.println(listDeserilized.get(0)==listDeserilized.get(1));**
System.out.println(listDeserilized.get(0)==listDeserilized.get(2));
并输出..
1018069468
1018069468
199675306
真正
假
-
1018069468
1018069468
199675306
假
假
如何解决这个问题?
我用杰克逊·李(Jackson lib)解决了我的问题 。
@JsonIdentityInfo
批注保护对象关系(换句话说,保护引用),反序列化后,对象位置在内存中@JsonIdentityInfo
更改。
最终代码:
package com.maar.projectbuilder;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Firat on 11.9.2014.
*/
public class Testt {
@JsonDeserialize(as=StringClazz.class)
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
@JsonTypeName(value = "StringClazz")
private static class StringClazz{
private String data="";
public StringClazz() {
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
public static void main(String[] args) throws IOException {
StringClazz someOfString=new StringClazz();
someOfString.setData("someOfString");
StringClazz differentString=new StringClazz();
differentString.setData("differentString");
List<StringClazz> list=new ArrayList<StringClazz>();
list.add(someOfString);
list.add(someOfString);
list.add(differentString);
for(Object str:list){
System.out.println(str.hashCode());
}
System.out.println(list.get(0)==list.get(1));
System.out.println(list.get(0)==list.get(2));
System.out.println("-------");
String json= null;
try {
json = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL).writeValueAsString(list);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
System.out.println(json);
List<StringClazz> listDeserilized =new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL).readValue(json, new TypeReference<List<StringClazz>>() {
});
for(Object str:listDeserilized){
System.out.println(str.hashCode());
}
System.out.println(listDeserilized.get(0)==listDeserilized.get(1));
System.out.println(listDeserilized.get(0)==listDeserilized.get(2));
}
}
如何解决这个问题?
你不知道 反序列化对象意味着在内存中的其他位置创建一个新实例。
但是, 我不建议这样做 ,您可以保留对象的注册表(也许是HashMap
),进行反序列化,检查注册表是否包含对象,然后将其替换为现有的对象。
String
类已经为您提供了一些使用Intern的行为。 参见String#intern()
。
您在努力奋斗是什么意思是平等? 在Java中,有两个相等的版本(与许多现代语言一样)。
这分别是.equals()和==之间的区别。 反序列化某些对象时,它会创建一个新对象,因此,如果您拥有该对象的另一个副本,则会进行序列化。 它永远不会等于2(即按引用相等)。 因为反序列化被赋予了JSON表示,并且它由此创建了一个新的对象图。
但这可能是.equals(),前提是您的对象正确定义了.equals()对包括的所有对象的含义。 默认情况下,Object.equals()比较引用,并且与==相同。 但是,每个对象都可以重载它,对于String.equals()而言,它会比较字符串的实际内容。
因此,只需将您的代码更改为使用.equals()而不是==,您将获得期望的结果:
System.out.println( list.get(0).equals( list.get(1) ) )
System.out.println( list.get(0).equals( list.get(2) ) )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.