我有一个将HashMap同步为类成员的情况。
public class Code {
private Code(String code) {
this.code = code;
}
public static Code newInstance(String code) {
if (code == null) {
throw new java.lang.IllegalArgumentException("code cannot be null");
}
return new Code(code);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + code.hashCode();
return result;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Code)) {
return false;
}
return this.code.equals(((Code)o).code);
}
@Override
public String toString() {
return code;
}
private String code;
}
public class AlertStateManager {
public boolean addFallBelow(Code code) {
fallBelows.put(code, System.currentTimeMillis());
return true;
}
public boolean addRiseAbove(Code code) {
riseAboves.put(code, System.currentTimeMillis());
return true;
}
public boolean removeFallBelow(Code code) {
return fallBelows.remove(code) != null;
}
public boolean removeRiseAbove(Code code) {
return riseAboves.remove(code) != null;
}
public void remove(Code code) {
fallBelows.remove(code);
riseAboves.remove(code);
}
public void remove() {
fallBelows.clear();
riseAboves.clear();
}
private final Map<Code, Long> fallBelows = java.util.Collections.synchronizedMap(new HashMap<Code, Long>());
private final Map<Code, Long> riseAboves = java.util.Collections.synchronizedMap(new HashMap<Code, Long>());
}
当我执行序列化和反序列化时,我得到以下内容
public static void main(String[] args) {
AlertStateManager alertStateManager = new AlertStateManager();
alertStateManager.addFallBelow(Code.newInstance("hello"));
alertStateManager.addRiseAbove(Code.newInstance("world"));
String json_alert_state_manager = null;
// WRITE
{
final Gson gson = new Gson();
json_alert_state_manager = gson.toJson(alertStateManager);
}
System.out.print(json_alert_state_manager);
// READ
{
final Gson gson = new Gson();
alertStateManager = gson.fromJson(json_alert_state_manager, AlertStateManager.class);
}
}
序列化
{"fallBelows":{"hello":1370356891664},"riseAboves":{"world":1370356891664}}
反序列化
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 17
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:186)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.Gson.fromJson(Gson.java:803)
at com.google.gson.Gson.fromJson(Gson.java:768)
at com.google.gson.Gson.fromJson(Gson.java:717)
at com.google.gson.Gson.fromJson(Gson.java:689)
at javaapplication6.JavaApplication6.main(JavaApplication6.java:38)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 17
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:374)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:165)
... 10 more
Java Result: 1
我能做些什么让它有效? 我正在使用Gson 2.2.3
答案 0 :(得分:3)
@MikO提供了很好的提示。经过几次实验,我发现在序列化过程中,我们需要构建以下
GsonBuilder builder = new GsonBuilder();
builder.enableComplexMapKeySerialization();
Gson gson = builder.create();
这将生成正确的json字符串。
{"fallBelows":[[{"code":"hello"},1370359852472]],"riseAboves":[[{"code":"world"},1370359852472]]}
请注意,在反序列化期间,为避免上述json字符串变为LinkedHashMap
,这是我们需要做的事情
private static class SynchronizedMapInstanceCreator<K, V> implements
InstanceCreator<Map<K, V>> {
@Override
public Map<K, V> createInstance(final Type type) {
return java.util.Collections.synchronizedMap(new HashMap<K, V>());
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
String json_alert_state_manager = "{\"fallBelows\":[[{\"code\":\"hello\"},1370359852472]],\"riseAboves\":[[{\"code\":\"world\"},1370359852472]]}";
// READ
{
Gson gson = new GsonBuilder().registerTypeAdapter(
new TypeToken<Map<Code, Long>>() {}.getType(),
new SynchronizedMapInstanceCreator<Code, Long>()).create();
AlertStateManager alertStateManager = gson.fromJson(json_alert_state_manager, AlertStateManager.class);
alertStateManager.debug();
}
}
答案 1 :(得分:1)
正如您告诉Gson它应该将"fallBelows"
(以及"riseAboves"
)元素的内容解析为Map<Code, Long>
,它预计会出现以下情况:
"fallBelows": { {codeObject}, someLong }
但它发现了这个:
"fallBelows": { "someString", someLong }
这就是为什么它抱怨说它已经消耗了一个对象(Code
),但它发现了一个字符串......
编辑:我刚刚意识到这对你来说可能很清楚,但是在地图序列化中一定存在问题,我会尝试检查......