我正在尝试使用Gson将涉及多态的对象序列化/反序列化为JSON.
这是我的序列化代码:
ObixBaseObj lobbyObj = new ObixBaseObj();
lobbyObj.setIs("obix:Lobby");
ObixOp batchOp = new ObixOp();
batchOp.setName("batch");
batchOp.setIn("obix:BatchIn");
batchOp.setOut("obix:BatchOut");
lobbyObj.addChild(batchOp);
Gson gson = new Gson();
System.out.println(gson.toJson(lobbyObj));
Run Code Online (Sandbox Code Playgroud)
这是结果:
{"obix":"obj","is":"obix:Lobby","children":[{"obix":"op","name":"batch"}]}
Run Code Online (Sandbox Code Playgroud)
序列化大多的作品,除了它缺少继承成员的内容(尤其是obix:BatchIn和obixBatchout字符串丢失).这是我的基类:
public class ObixBaseObj {
protected String obix;
private String display;
private String displayName;
private ArrayList<ObixBaseObj> children;
public ObixBaseObj()
{
obix = "obj";
}
public void setName(String name) {
this.name = name;
}
...
}
Run Code Online (Sandbox Code Playgroud)
这是我继承的类(ObixOp)的样子:
public class ObixOp extends ObixBaseObj {
private String in;
private String out;
public ObixOp() { …Run Code Online (Sandbox Code Playgroud) 我找不到在Gson中序列化期间添加自定义字段的简单方法,我希望其他人可以提供帮助.
这是一个展示我的问题的示例类:
public class A {
String id;
String name;
...
}
Run Code Online (Sandbox Code Playgroud)
当我序列化类时,AI想要返回类似的东西:
{ "id":"123", "name":"John Doe", "url_to_user":"http://www.example.com/123" }
Run Code Online (Sandbox Code Playgroud)
其中url_to_user未存储在我的A类实例中,但可以使用A类实例中的数据生成.
有一个简单的方法吗?我宁愿避免编写整个序列化程序只是为了添加一个字段.
这是我的Retrofit实例:
@Provides
@Singleton
ApiManager provideApiManager() {
RxJava2CallAdapterFactory rxAdapter = RxJava2CallAdapterFactory.create();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addNetworkInterceptor(new StethoInterceptor())
.build();
Gson gson = new GsonBuilder().create();
GsonConverterFactory converterFactory = GsonConverterFactory.create(gson);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(AppConstants.BASE_URL)
.addConverterFactory(converterFactory)
.addCallAdapterFactory(rxAdapter)
.client(okHttpClient)
.build();
return retrofit.create(ApiManager.class);
}
Run Code Online (Sandbox Code Playgroud)
模型:
class AbstractMessage {
String id;
}
class TextMessage extends AbstractMessage {
String textMessage;
}
class ImageMessage extends AbstractMessage {
String url;
String text;
}
Run Code Online (Sandbox Code Playgroud)
请求:
@GET("direct/messages")
Observable<List<AbstractMessage>> getMessages(@Header("Authorization") String authHeader, @Body RequestObject request);
Run Code Online (Sandbox Code Playgroud)
执行请求:
apiManager.getMessages(authHeader, requestObject)
.subscribeOn(Schedulers.io()) …Run Code Online (Sandbox Code Playgroud) 我有以下类层次结构
public abstract class SyncModel {
@Expose
@SerializedName("id")
private Long globalId;
@Expose
protected DateTime lastModified;
/* Constructor, methods... */
}
public class Event extends SyncModel {
@Expose
private String title;
/* Other fields, constructor, methods... */
}
Run Code Online (Sandbox Code Playgroud)
我需要向后端发送一个Event实例.
@Body当我在请求正文中发布Event实例时,它被序列化了.
RetroFit Java界面:
public interface EventAPI {
@POST("/event/create")
void sendEvent(@Body Event event, Callback<Long> cbEventId);
}
Run Code Online (Sandbox Code Playgroud)
RetroFit日志:
D Retrofit ---> HTTP POST http://hostname:8080/event/create
D Retrofit Content-Type: application/json; charset=UTF-8
D Retrofit Content-Length: 297
D Retrofit {"title":"Test Event 01",...,"id":null,"lastModified":"2015-07-09T14:17:08.860+03:00"}
D Retrofit ---> END … 在我的情况下,当我将子类对象放入改装请求时,它在请求体中变为空白
interface User{ // my super interface
}
class FbUser implements User{ // my sub class
public String name;
public String email;
}
interface APIInterface{
@POST(APIConstants.LOGIN_URL)
Observable<LoginAPIResponse> createUserNew(@Body User user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.addCallAdapterFactory(RxErrorHandlingCallAdapterFactory.create())
.client(okHttpClient)
.build();
APIInterface networkAPI = retrofit.create(APIInterface.class);
Run Code Online (Sandbox Code Playgroud)
现在我过世了 FbUserObject
networkAPI.createUserNew(fbUserObject).subscribe();
Run Code Online (Sandbox Code Playgroud)
然后物体在身体上变成空白.看我的日志
D/OkHttp: Content-Type: application/json; charset=UTF-8
D/OkHttp: Content-Length: 2
D/OkHttp: Accept: application/json
D/OkHttp: TT-Mobile-Post: post
D/OkHttp: {}
D/OkHttp: --> END POST (2-byte body)
Run Code Online (Sandbox Code Playgroud)
我也经历了这个stackover流程链接Polymorphism与gson
我应该写自己的Gson转换器吗?
出于某种未知原因,如果我有:
class A{
int stars;
public int getStars(){
return stars;
}
public void setStarts(int stars){
this.stars = stars;
}
}
class B extends A{
int sunshines;
[getter and setter for sunshines]
}
class C{
List<A> classes;
[get and set for classes]
}
Run Code Online (Sandbox Code Playgroud)
如果我序列化类型CI的对象在字段类中的序列化对象中只有A的字段(如果对象是B,我希望有B的字段).
怎么做?
使用Gson 2.2.2我正在尝试序列化POJO(行为)的数组列表.
我有一个适配器几乎是我在网上看到的副本:
public class BehaviorAdapter implements JsonSerializer<Behavior> {
private static final String CLASSNAME = "CLASSNAME";
private static final String INSTANCE = "INSTANCE";
@Override
public JsonElement serialize(Behavior src, Type typeOfSrc,
JsonSerializationContext context) {
JsonObject retValue = new JsonObject();
String className = src.getClass().getCanonicalName();
retValue.addProperty(CLASSNAME, className);
JsonElement elem = context.serialize(src);
retValue.add(INSTANCE, elem);
return retValue;
}
}
Run Code Online (Sandbox Code Playgroud)
我这样注册:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeHierarchyAdapter(Behavior.class, new BehaviorAdapter());
gson = builder.create();
Run Code Online (Sandbox Code Playgroud)
然后,当我尝试序列化我的ArrayList时:
String json2 = gson.toJson(behaviors);
Run Code Online (Sandbox Code Playgroud)
我得到一个堆栈溢出.
它似乎在线:
JsonElement elem = context.serialize(src);
Run Code Online (Sandbox Code Playgroud)
它启动一个递归循环,一次又一次地通过我的序列化器.那么如何注册它以便不会发生这种情况?我需要序列化列表并维护多态性.
我目前正在使用GSON将我的JSON解析为Objects.我使用的标准方式如下:
Result response= gson.fromJson(reader, Result.class);
Run Code Online (Sandbox Code Playgroud)
结果可以是具有其他复杂对象的非常复杂的对象,最多具有5个级别的复杂对象.但我对此没有任何问题.我的问题是:我希望能够在某些对象中具有灵活类型的属性.
例如 :
class Class1 {
String hello;
}
class Class2 {
String world;
}
class Class3 {
Class<?> (= class1 or class2) hello;
}
// Parsing time
Class<?> response= gson.fromJson(reader, Class3.class);
try {
Class1 ret = (Class1)response;
} catch ... {
Class2 ret = (Class2)response;
}
Run Code Online (Sandbox Code Playgroud)
希望它足够清楚.