我正在构建 Android应用,它使用JSON与C#服务器进行通信。
我有一个要序列化的数据类(实际上,要将接收到的数据反序列化),它包含派生类的List字段,但将它们存储为它们的基类:
public class shortpa {
public int distance;
public int parentVert;
public char label;
public boolean isInTree;
public final int MAX_VERTS=20;
public final int INFINITY=1000000;
public Vertex vertexList[];
public int adjMat[][];
public int nVerts;
public int nTree;
public DistPar sPath[];
public int currentVert;
public int startToCurrent;
public static void main(String[] args)
{
Graph theGraph = new Graph();//error here saying graph can nt be resolved to a type
theGraph.addVertex('A');
theGraph.addVertex('B');
theGraph.addVertex('C');
theGraph.addVertex('D');
theGraph.addVertex('Z');
theGraph.addEdge(1, 2, 10);//1 repesents A, 2 repesents B....etc and 10 is the weight
theGraph.addEdge(1, 5, 18);
theGraph.addEdge(2, 3, 3);
theGraph.addEdge(2, 5,17);
theGraph.addEdge(2, 4, 1);
theGraph.addEdge(3, 4, 1);
theGraph.addEdge(4, 5, 4);
System.out.println("Shortest paths");
theGraph.path();
System.out.println();
}
//--------------------------------------------------------------------------
public void DistPar(int pv, int d)
{
distance = d;
parentVert=pv;
}
//--------------------------------------------------------------------------
public void Vertex(char lab)
{
label = lab;
isInTree = false;
}
//--------------------------------------------------------------------------
public void Graph()
{
vertexList = new Vertex[MAX_VERTS];/////error here saying vertex can not be resolved to a type
adjMat = new int[MAX_VERTS][MAX_VERTS];
nVerts=0;
nTree=0;
for(int j =0; j<MAX_VERTS; j++)
for(int k=0; k<MAX_VERTS; k++)
adjMat[j][k] = INFINITY;
sPath = new DistPar[MAX_VERTS];//error here saying distpar can not be resolved to a type
}
//--------------------------------------------------------------------------
public void addVertex(char lab)
{
vertexList[nVerts++] = new Vertex(lab);
}
//-------------------------------------------------------------------------
public void addEdge(int start, int end, int weight)////have a look here
{
adjMat[start][end]=weight;
}
//--------------------------------------------------------------------
public void path()
{
int startTree = 0;
vertexList[startTree].isInTree = true;
nTree = 1;
for(int j=0; j<nVerts; j++)
{
int tempDist = adjMat[startTree][j];
sPath[j] = new DistPar(startTree, tempDist);
}
while(nTree < nVerts)
{
int indexMin = getMin();
int minDist = sPath[indexMin].distance;
if(minDist == INFINITY)
{
System.out.println("Unreachable vertexs");
break;
}
else
{
currentVert=indexMin;
startToCurrent=sPath[indexMin].distance;
}
vertexList[currentVert].isInTree = true;
nTree++;
adjust_sPath();
}
displayPaths();
nTree = 0;
for(int j=0; j<nVerts; j++)
vertexList[j].isInTree = false;
}
//---------------------------------------------------------------------------
public int getMin()
{
int minDist = INFINITY;
int indexMin = 0;
for(int j=1; j<nVerts;j++)
{
if(!vertexList[j].isInTree && sPath[j].distance < minDist)
{
minDist = sPath[j].distance;
indexMin = j;
}
}
return indexMin;
}
//------------------------------------------------------------------------------
public void adjust_sPath()
{
int column = 1;
while(column < nVerts)
{
if(vertexList[column].isInTree)
{
column++;
continue;
}
int currentToFringe = adjMat[currentVert][column];
int startToFringe = startToCurrent + currentToFringe;
int sPathDist = sPath[column].distance;
if(startToFringe < sPathDist)
{
sPath[column].parentVert = currentVert;
sPath[column].distance = startToFringe;
}
column++;
}
}
//------------------------------------------------------------------------------
public void displayPaths()
{
for(int j=0; j< nVerts; j++)
{
System.out.println(vertexList[j].label+"=");
if(sPath[j].distance == INFINITY)
System.out.println("inf");
else
System.out.println(sPath[j].distance);
char parent = vertexList[sPath[j].parentVert].label;
System.out.println(" (" + parent + ") ");
}
System.out.println("");
}
}
例如,如果我正在接收以下ToSerializeClass实例,来自C#端,名为 serializeClass :
public class ToSerializeClass{
@SerializedName("TestString")
private String testString = "TestStringValue";
@SerializedName("DerivedClasses")
private List<BaseClass> derivedClasses;
public List<BaseClass> getDerivedClasses() {
return derivedClasses;
}
public ToSerializeClass(List<BaseClass> derivedClasses){
this.derivedClasses= derivedClasses;
}
}
JSON字符串将是:
List<BaseClass> derivedClasses = new ArrayList<>();
derivedClasses.add(new DerivedClassA());
derivedClasses.add(new DerivedClassB());
ToSerializeClass serializeClass = new ToSerializeClass(derivedClasses);
JSON字符串的&#34; __ type&#34;:#34; SimpleClassName&#34; 字段显示序列化类的简单名称。这些是由C#side的序列化程序添加的。 如果有必要的话,我可以让这些字段消失,但这是C#方面同样问题的解决方案。 没有类型,它看起来像这样:
{"__type":"ToSerializeClass","DerivedClasses":[{"__type":"DerivedA","FieldA":"This is a derived class."},{"__type":"DerivedB","FieldB":"This is ANOTHER derived class.", "IntValue":10}],"TestString":"TestStringValue"}
问题是,当我尝试反序列化 JSON字符串到 ToSerializeClass 类的实例时:
{"DerivedClasses":[{"FieldA":"This is a derived class."},{"FieldB":"This is ANOTHER derived class.", "IntValue":10}],"TestString":"TestStringValue"}
我有反序列化的类,它是 ToSerializeClass 实例,但 derivedClasses List是基类而不是派生类的集合,并且所有派生的信息都会丢失。
如何将String反序列化为 ToSerializeClass 实例以获得派生类的列表?
我可以完全控制源代码,因此我可以修改我的数据类,在必要时使用不同的集合来创建一些包装器,修改JSON字符串,但是我可以喜欢尽可能使用Gson解决它,并且可以在没有太多开销的情况下完成。
谢谢!
编辑,例如 DerivedClassA 和 DerivedClassB :
Gson serializer = new Gson();
ToSerializeClass deserialized = serializer.fromJson(jsonString, ToSerializeClass.class);
答案 0 :(得分:0)
我已经创建了一个快速的解决方案,它接近我正在寻找的解决方案(我不是一个Java人员,所以如果它伤害了你的大脑,我很抱歉,随时评论建议)。
数据类:
public class BaseClass {
@SerializedName("Method")
private String method;
public void setMethod(String method){
this.method = method;
}
public String getMethod(){
return method;
}
public BaseClass(String method){
this.method = method;
}
}
public class DerivedClassA extends BaseClass{
@SerializedName("FieldA")
private String fieldA = "This is a derived class.";
public DerivedClassA(){
super("ClassA");
}
}
public class DerivedClassB extends BaseClass{
@SerializedName("FieldB")
private String fieldB = "This is ANOTHER derived class.";
@SerializedName("IntValue")
private int intValue = 10;
public DerivedClassB(){
super("ClassB");
}
}
public class ToSerializeClass{
@SerializedName("TestString")
private String testString = "TestStringValue";
@SerializedName("DerivedClasses")
private List<BaseClass> derivedClasses;
public ToSerializeClass(List<BaseClass> derivedClasses){
this.derivedClasses= derivedClasses;
}
}
解决方案: ClassDeserializerAdapter 实施:
public class ClassDeserializerAdapter implements JsonDeserializer<BaseClass>
{
private String typeName;
private Gson gson;
private Map<String, Class<? extends BaseClass>> classTypeRegistry;
ClassDeserializerAdapter(String typeName)
{
this.typeName = typeName;
gson = new Gson();
classTypeRegistry = new HashMap<>();
}
void registerClassType(String classTypeName, Class<? extends BaseClass> classType)
{
// registering Types to Strings
classTypeRegistry.put(classTypeName, classType);
}
@Override
public BaseClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
JsonObject jsonObject = json.getAsJsonObject();
JsonElement typeElement = jsonObject.get(typeName);
String method = typeElement.getAsString();
Class<? extends BaseClass> classType = classTypeRegistry.get(method);
BaseClass result = gson.fromJson(json, classType);
return result;
}
}
这对我来说很好,甚至没有临时课程等。
注意:通过反射,它可以自动注册从BaseClass继承的每个类,您甚至不必处理注册过程。
示例: main()方法的正文是:
// **SERIALIZATION PART** (nothing special, simple Gson serialization)
// Creating a list to pass as parameter to the container class
List<BaseClass> derivedClasses = new ArrayList<>();
derivedClasses.add(new DerivedClassA());
derivedClasses.add(new DerivedClassB());
// Creating the container class to be serialized
ToSerializeClass serializeClass = new ToSerializeClass(derivedClasses);
Gson gson = new Gson();
String json = gson.toJson(serializeClass);
// json = {"TestString":"TestStringValue","DerivedClasses":[{"FieldA":"This is a derived class.","Method":"ClassA"},{"FieldB":"This is ANOTHER derived class.","IntValue":10,"Method":"ClassB"}]}
// **DESERIALIZATION PART** (with custom deserializer)
// creating the custom deserializer, which will find the derived class' type as the class' "Method" field value. With that value, it can resolve the type.. see below
ClassDeserializerAdapter deserializer = new ClassDeserializerAdapter("Method");
// registering each Type into the Deserializer's HashMap (key-value pair), where the key (String) must be carried by the object (you can find it in the BaseClass, called "Method")
deserializer.registerClassType("ClassA", DerivedClassA.class);
deserializer.registerClassType("ClassB", DerivedClassB.class);
Gson gsonB = new GsonBuilder().registerTypeAdapter(BaseClass.class, deserializer).create();
// deserializing
ToSerializeClass deserialized = gsonB.fromJson(json, ToSerializeClass.class); // CORRECT!
答案 1 :(得分:-1)
使用此类
import com.google.gson.annotations.SerializedName;
public class DerivedClass {
@SerializedName("__type")
private String __type;
@SerializedName("FieldA")
private String fieldA;
@SerializedName("FieldB")
private String fieldB;
public String get__type() {
return __type;
}
public void set__type(String __type) {
this.__type = __type;
}
public String getFieldA() {
return fieldA;
}
public void setFieldA(String fieldA) {
this.fieldA = fieldA;
}
public String getFieldB() {
return fieldB;
}
public void setFieldB(String fieldB) {
this.fieldB = fieldB;
}
}
让Response.java
获得JSON
数据
import java.util.ArrayList;
import com.google.gson.annotations.SerializedName;
public class Response {
@SerializedName("__type")
private String __type;
@SerializedName("DerivedClasses")
private ArrayList<DerivedClass> derivedClasses;
@SerializedName("TestString")
private String testString;
public String get__type() {
return __type;
}
public void set__type(String __type) {
this.__type = __type;
}
public ArrayList<DerivedClass> getDerivedClasses() {
return derivedClasses;
}
public void setDerivedClasses(ArrayList<DerivedClass> derivedClasses) {
this.derivedClasses = derivedClasses;
}
public String getTestString() {
return testString;
}
public void setTestString(String testString) {
this.testString = testString;
}
}
现在您所要做的就是使用此行,您将获得数据
Response response = (new Gson()).fromJson("your_JSON", Response.class);