Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Gson反序列化映射键需要一个对象_Java_Json_Serialization_Deserialization_Gson - Fatal编程技术网

Java 使用Gson反序列化映射键需要一个对象

Java 使用Gson反序列化映射键需要一个对象,java,json,serialization,deserialization,gson,Java,Json,Serialization,Deserialization,Gson,我得到一个错误: Exception in thread "main" com.google.gson.JsonParseException: Expecting object found: "com.shagie.app.SimpleMap$Data@24a37368" 尝试反序列化使用非平凡键的映射时: package com.shagie.app; import com.google.gson.Gson; import com.google.gson.GsonBuilder; im

我得到一个错误:

Exception in thread "main" com.google.gson.JsonParseException: 
Expecting object found: "com.shagie.app.SimpleMap$Data@24a37368"
尝试反序列化使用非平凡键的映射时:

package com.shagie.app;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.util.HashMap;

public class SimpleMap {
    public static void main(String[] args) {
        Wrapper w = new Wrapper();
        w.m.put(new Data("f", 1), new Data("foo", 3));
        w.m.put(new Data("b", 2), new Data("bar", 4));

        GsonBuilder gb = new GsonBuilder();
        gb.setPrettyPrinting();
        Gson g = gb.create();

        String json = g.toJson(w);

        System.out.println(json);

        w = g.fromJson(json, Wrapper.class);
        System.out.println(w.m.isEmpty());
    }

    static public class Wrapper {
        HashMap<Data, Data> m = new HashMap<Data, Data>();
    }

    static public class Data {
        String s;
        Integer i;
        public Data(String arg, Integer val) { s = arg; i = val; }
    }
}
package com.shagie.app;
导入com.google.gson.gson;
导入com.google.gson.GsonBuilder;
导入java.util.HashMap;
公共类SimpleMap{
公共静态void main(字符串[]args){
包装器w=新包装器();
w、 m.put(新数据(“f”,1),新数据(“foo”,3));
w、 m.put(新数据(“b”,2),新数据(“条形图”,4));
GsonBuilder gb=新的GsonBuilder();
gb.setPrettyPrinting();
Gson g=gb.create();
字符串json=g.toJson(w);
System.out.println(json);
w=g.fromJson(json,Wrapper.class);
System.out.println(w.m.isEmpty());
}
静态公共类包装器{
HashMap m=新的HashMap();
}
静态公共类数据{
字符串s;
整数i;
公共数据(字符串arg,整数val){s=arg;i=val;}
}
}
这将序列化为json:

{ "m": { "com.shagie.app.SimpleMap$Data@24a37368": { "s": "foo", "i": 3 }, "com.shagie.app.SimpleMap$Data@66edc3a2": { "s": "bar", "i": 4 } } } { “m”:{ “com.shagie.app.SimpleMap$Data@24a37368": { “s”:“foo”, “i”:3 }, “com.shagie.app.SimpleMap$Data@66edc3a2": { “s”:“bar”, “i”:4 } } } 可以看到密钥试图被序列化,但肯定不是以反序列化的方式


如何序列化此对象以便将其反序列化?

问题在于
toString()
在映射的键上被调用,而不是它们自己被序列化

要解决此问题,需要设置自定义序列化程序和反序列化程序,反序列化程序需要知道对象用于将自身显示为字符串的格式(
toString()
方法必须返回可用于重建整个对象的字符串)

对于上述示例:

package com.shagie.app;

import com.google.gson.*;

import java.lang.reflect.Type;
import java.util.HashMap;

public class SimpleMapFixed {
    public static void main(String[] args) {
        Wrapper w = new Wrapper();
        w.m.put(new Data("f", 1), new Data("foo", 3));
        w.m.put(new Data("b", 2), new Data("bar", 4));

        GsonBuilder gb = new GsonBuilder();
        gb.setPrettyPrinting();
        gb.registerTypeAdapter(Data.class, new DataSerializer());
        Gson g = gb.create();

        String json = g.toJson(w);
        System.out.println(json);

        w = g.fromJson(json, Wrapper.class);
        System.out.println(w.m.isEmpty());
    }

    static public class Wrapper {
        HashMap<Data, Data> m = new HashMap<Data, Data>();
    }

    static public class DataSerializer implements JsonSerializer<Data>,
                                                  JsonDeserializer<Data> {
        @Override
        public Data deserialize(JsonElement je, Type t, JsonDeserializationContext ctx)
                throws JsonParseException {
            Data rv;
            JsonObject jo;

            System.out.println("deserialize called with: " + je.toString());

            if (je.isJsonObject()) {
                jo = je.getAsJsonObject();
                rv = new Data(jo.get("s").getAsString(), jo.get("i").getAsInt());
            } else {
                String js = je.getAsString();
                String[] s = js.split(":", 2);  // split into two (and only two)
                rv = new Data(s[1], Integer.valueOf(s[0]));
            }

            System.out.println("deserialize returns: " + rv.s + " " + rv.i);
            return rv;
        }

        @Override
        public JsonElement serialize(Data data, Type type, JsonSerializationContext jsonSerializationContext) {
            JsonObject jo = new JsonObject();
            jo.addProperty("s", data.s);
            jo.addProperty("i", data.i);
            System.out.println("serialize called: " + jo.toString());
            return jo;
        }
    }

    static public class Data {
        String s;
        Integer i;

        public Data(String arg, Integer val) { s = arg; i = val; }

        @Override
        public String toString() {
            String rv = i.toString() + ':' + s;
            System.out.println("toString called: " + rv);
            return rv;
        }
    }
}
package com.shagie.app;
导入com.google.gson.*;
导入java.lang.reflect.Type;
导入java.util.HashMap;
公共类simplemapfix{
公共静态void main(字符串[]args){
包装器w=新包装器();
w、 m.put(新数据(“f”,1),新数据(“foo”,3));
w、 m.put(新数据(“b”,2),新数据(“条形图”,4));
GsonBuilder gb=新的GsonBuilder();
gb.setPrettyPrinting();
gb.registerTypeAdapter(Data.class,新的DataSerializer());
Gson g=gb.create();
字符串json=g.toJson(w);
System.out.println(json);
w=g.fromJson(json,Wrapper.class);
System.out.println(w.m.isEmpty());
}
静态公共类包装器{
HashMap m=新的HashMap();
}
静态公共类DataSerializer实现JsonSerializer,
JsonDeserializer{
@凌驾
公共数据反序列化(JsonElement je,类型t,JsonDeserializationContext ctx)
抛出JsonParseException{
数据rv;
JsonObject jo;
System.out.println(“反序列化调用:“+je.toString()”);
if(je.isJsonObject()){
jo=je.getAsJsonObject();
rv=新数据(jo.get(“s”).getAsString(),jo.get(“i”).getAsInt());
}否则{
字符串js=je.getAsString();
String[]s=js.split(“:”,2);//拆分为两个(并且只有两个)
rv=新数据(s[1],整数.valueOf(s[0]);
}
System.out.println(“反序列化返回:+rv.s+”+rv.i);
返回rv;
}
@凌驾
公共JsonElement序列化(数据数据、类型、JsonSerializationContext JsonSerializationContext){
JsonObject jo=新的JsonObject();
jo.addProperty(“s”,data.s);
jo.addProperty(“i”,data.i);
System.out.println(“序列化调用:”+jo.toString());
返回jo;
}
}
静态公共类数据{
字符串s;
整数i;
公共数据(字符串arg,整数val){s=arg;i=val;}
@凌驾
公共字符串toString(){
字符串rv=i.toString()+':'+s;
System.out.println(“称为“+rv”的toString);
返回rv;
}
}
}
运行此代码会产生:

serialize called: {"s":"foo","i":3} toString called: 1:f serialize called: {"s":"bar","i":4} toString called: 2:b { "m": { "1:f": { "s": "foo", "i": 3 }, "2:b": { "s": "bar", "i": 4 } } } deserialize called with: "1:f" deserialize returns: f 1 deserialize called with: {"s":"foo","i":3} deserialize returns: foo 3 deserialize called with: "2:b" deserialize returns: b 2 deserialize called with: {"s":"bar","i":4} deserialize returns: bar 4 序列化名为:{“s”:“foo”,“i”:3} toString调用:1:f 序列化名为:{“s”:“bar”,“i”:4} toString调用:2:b { “m”:{ “1:f”:{ “s”:“foo”, “i”:3 }, “2:b”:{ “s”:“bar”, “i”:4 } } } 用“1:f”反序列化调用 反序列化返回:f 1 用{“s”:“foo”,“i”:3}反序列化调用 反序列化返回:foo3 用“2:b”反序列化调用 反序列化返回:b2 用{“s”:“bar”,“i”:4}反序列化调用 反序列化返回:条4 请注意,调用
toString()
是序列化的一部分。在这段代码中,字符串形式的反序列化逻辑位于
数据序列化程序
中,尽管将其作为另一个构造函数移动到
数据
类中可能是有意义的-它不会影响最终结果


进一步注意,
数据
本身是一个相当简单的对象,没有更深层次的结构。尝试序列化该键需要额外的工作。

这取决于您如何维护HahMap键,您可以用简单而简单的方法将其反序列化

final Type typeOf = new TypeToken <Map<String, Map<String, Data>>>(){}.getType();
final  Map<String, Map<String, Data>> newMap = gson.fromJson(json, typeOf);
final Map<String, Data> map = newMap.get("m");
final Iterator<Entry<String, Data>> it = map.entrySet().iterator();

while (it.hasNext()) {
   Map.Entry<String,Data> pair = (Map.Entry<String,Data>) it.next();
   String key = pair.getKey();
   System.out.println("key  "+ key + " Values[  i= " + data.getI() + ", s= " +data.getS()+" ]");
       }
final-Type-typeOf=new-TypeToken(){}.getType();
最终映射newMap=gson.fromJson(json,typeOf);
最终映射=newMap.get(“m”);
final Iterator it=map.entrySet().Iterator();
while(it.hasNext()){
Map.Entry对=(Map.Entry)it.next();
String key=pair.getKey();
System.out.println(“key”+key+”值[i=“+data.getI()+”,s=“+data.getS()+”]);
}
结果:

key=snippet.snippet$Data@61506150值[i=3,s=foo]


key=snippet.snippet$Data@63ff63ff值[i=4,s=bar]

我在尝试解决此难题时发现了以下内容:

对于来自美国的任何互联网旅行者
{"m":[[{"s":"f", "i",1}, {"s":"foo", "i":3}], [{"s":"b", "i",2}, {"s":"bar", "i":4}]]}