Jersey Jackson Serializing Parent Fields - java

I have an object "A" which extends object "B" when object "A" gets serialized the fields from object "B" do not get serialized into JSON. Any Ideas? Here are my objects involved.
public class CreateNewPlayerAndLoginResponse extends EPNetResponse{
private PlayerSession playerSession;
public CreateNewPlayerAndLoginResponse() {
}
public CreateNewPlayerAndLoginResponse(Integer playerId, String playerSessionId) {
this.playerSession = new PlayerSession(playerId, playerSessionId);
}
public CreateNewPlayerAndLoginResponse(EPNetErrorEnum error) {
super(error);
}
public CreateNewPlayerAndLoginResponse(EPNetError error) {
super(error);
}
public PlayerSession getPlayerSession() {
return playerSession;
}
public void setPlayerSession(PlayerSession playerSession) {
this.playerSession = playerSession;
}
#Override
public String toString() {
return "CreateNewPlayerAndLoginResponse{" + "playerSession=" + playerSession + '}';
}
}
public class EPNetResponse implements Serializable{
private EPNetError error;
public EPNetResponse() {
}
public EPNetResponse(EPNetError error) {
this.error = error;
}
public EPNetResponse(EPNetErrorEnum error){
this.error = new EPNetError(error);
}
public EPNetError getError() {
return error;
}
public void setError(EPNetError error) {
this.error = error;
}
#JsonIgnore
public boolean isError(){
if(error == null){
return false;
}
return true;
}
}
public class EPNetError implements Serializable{
private static final int UNEXPECTED_ERROR = 5417;
private Integer code;
private String message;
public EPNetError() {
}
public EPNetError(EPNetErrorEnum error){
this.code = error.getCode();
this.message = error.getMessage();
}
public EPNetError(EPNetErrorEnum error, String message){
this.code = error.getCode();
this.message = message;
}
public EPNetError(String message){
this.code = EPNetError.UNEXPECTED_ERROR;
this.message = message;
}
public EPNetError(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
All I get as the serialized response is
{"playerSession":null}
Even though I am 100% sure there is an error message part of the object before serialization.
Also worth mentioning I am using Jackson 1.9.2 and Jersey 1.13

If you are expecting 'error' to be included, problem is that #JsonIgnore in isError(), without any other annotations. So, add #JsonProperty next to getError() and it should be included. You may also need to add it to setError().
The problem here is that Jackson consider #JsonIgnore here to mean "ignore property 'error'", whereas you are probably only hoping to ignore that particular accessor.

Related

How to write junit for "this" keywrd and for the following method. I only know basics and stuck with this

Since am new to junit am finding it confusing for such methods. Any hints or solution will be appreciated.
I am able to write testcases for some math operations, but not able to write for such methods.
public class ErrorThreshold {
private String attributeType = null;
private String errorCode = null;
public ErrorThreshold()
{
}
public ErrorThreshold(String attributeType, String errorCode)
{
this.attributeType = attributeType;
this.errorCode = errorCode;
}
public String getAttributeType() {
return attributeType;
}
public void setAttributeType(String attributeType) {
this.attributeType = attributeType;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}

Retrofit + Observable - Expected BEGIN_ARRAY but was BEGIN_OBJECT

I'm trying to use New York Times API with Retrofit using Observable. But I'm getting this error when trying to use datas.
Can someone help me see where I'm wrong, please ?
Here is my ApiServices interface:
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<TopStoryResult> getTopStories();
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<List<NewsItem>> getResults();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.nytimes.com/")
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
Here is my ApiStreams class
public static Observable<TopStoryResult> streamFetchTopStories(){
ApiServices mApiServices = ApiServices.retrofit.create(ApiServices.class);
return mApiServices.getTopStories()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(10, TimeUnit.SECONDS);
}
public static Observable<List<NewsItem>> streamFetchNews(){
ApiServices mApiServices = ApiServices.retrofit.create(ApiServices.class);
return mApiServices.getResults()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(10, TimeUnit.SECONDS);
}
And this is what I'm trying to do in my MainActivity. For now I just want to display in a TextView the list of each Title...
//------------------------
// Update UI
//------------------------
private void updateUIWhenStartingHttpRequest() {
this.textView.setText("Downloading...");
}
private void updateUIWhenStopingHttpRequest(String response) {
this.textView.setText(response);
}
//------------------------
// Rx Java
//------------------------
private void executeRequestWithRetrofit(){
this.updateUIWhenStartingHttpRequest();
this.disposable = ApiStreams.streamFetchNews()
.subscribeWith(new DisposableObserver<List<NewsItem>>(){
#Override
public void onNext(List<NewsItem> topStories) {
Log.e("TAG", "On Next");
updateUIWithResult(topStories);
}
#Override
public void onError(Throwable e) {
Log.e("ERROR", Log.getStackTraceString(e));
}
#Override
public void onComplete() {
Log.e("TAG", "On Complete !");
}
});
}
private void updateUIWithResult(List<NewsItem> newsItemList){
StringBuilder mStringBuilder = new StringBuilder();
for (NewsItem news : newsItemList){
Log.e("TAG", "UPDATE UI" + news.getTitle());
mStringBuilder.append("- " + news.getTitle() + "\n");
}
updateUIWhenStopingHttpRequest(mStringBuilder.toString());
}
[EDIT]
There are my two models for TopStories and NewsItem
TopStories:
private String status;
private String copyright;
private String section;
private String lastUpdated;
private Integer numResults;
private List<NewsItem> results = null;
public String getStatus() {return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getCopyright() {
return copyright;
}
public void setCopyright(String copyright) {
this.copyright = copyright;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
public String getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(String lastUpdated) {
this.lastUpdated = lastUpdated;
}
public Integer getNumResults() {
return numResults;
}
public void setNumResults(Integer numResults) {
this.numResults = numResults;
}
public List<NewsItem> getResults() {
return results;
}
public void setResults(List<NewsItem> results) {
this.results = results;
}
NewsItem:
private String section;
private String subsection;
private String title;
private String url;
private String byline;
private String updated_date;
private String created_date;
private String published_date;
private String material_type_facet;
private String kicker;
#SerializedName("abstract")
private String abstract_string;
private List<Multimedia> multimedia;
private transient String des_facet;
private transient String org_facet;
private transient String per_facet;
private transient String geo_facet;
public NewsItem() {
}
public NewsItem(String url) {
this.url = url;
}
public NewsItem(String section, String subsection, String title, String url, String byline, String updated_date, String created_date, String published_date, String material_type_facet, String kicker) {
this.section = section;
this.subsection = subsection;
this.title = title;
this.url = url;
this.byline = byline;
this.updated_date = updated_date;
this.created_date = created_date;
this.published_date = published_date;
this.material_type_facet = material_type_facet;
this.kicker = kicker;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
public String getSubsection() {
return subsection;
}
public void setSubsection(String subsection) {
this.subsection = subsection;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getByline() {
return byline;
}
public void setByline(String byline) {
this.byline = byline;
}
public String getUpdated_date() {
return updated_date;
}
public void setUpdated_date(String updated_date) {
this.updated_date = updated_date;
}
public String getCreated_date() {
return created_date;
}
public void setCreated_date(String created_date) {
this.created_date = created_date;
}
public String getPublished_date() {
return published_date;
}
public void setPublished_date(String published_date) {
this.published_date = published_date;
}
public String getMaterial_type_facet() {
return material_type_facet;
}
public void setMaterial_type_facet(String material_type_facet) {
this.material_type_facet = material_type_facet;
}
public String getKicker() {
return kicker;
}
public void setKicker(String kicker) {
this.kicker = kicker;
}
public String getAbstract() {
return abstract_string;
}
public void setAbstract(String abstract_string) {
this.abstract_string = abstract_string;
}
public List<Multimedia> getMultimedia() {
return multimedia;
}
public void setMultimedia(List<Multimedia> multimedia) {
this.multimedia = multimedia;
}
public String getDes_facet() {
return des_facet;
}
public void setDes_facet(String des_facet) {
this.des_facet = des_facet;
}
public String getOrg_facet() {
return org_facet;
}
public void setOrg_facet(String org_facet) {
this.org_facet = org_facet;
}
public String getPer_facet() {
return per_facet;
}
public void setPer_facet(String per_facet) {
this.per_facet = per_facet;
}
public String getGeo_facet() {
return geo_facet;
}
public void setGeo_facet(String geo_facet) {
this.geo_facet = geo_facet;
}
Here is what the JSON looks like:
JSON
First when I tried this one with Github user API, it works fine. But I can't figure out where I'm wrong there...
Is anybody can help me please ?
Thanks a lot !
Expected BEGIN_ARRAY but was BEGIN_OBJECT
this means you are trying to a get a JSON Array as a List in JAVA but the api sent you a JSON OBJECT. So I cannot gather enough information but if I have to guess you should change this
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<List<NewsItem>> getResults();
to
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<NewsItemObject> getResults();
NewsItemObject is the Class that wraps NewsItem
In your ApiServices interface you expect that getResults() returns Observable<List<NewsItem>>. Based on JSON you getting back this is not gonna work, because your root JSON element is Object, not an Array.
You have to create new wrapper Class (ResultsWrapper) with "results" field type of List<NewsItem>. Your method in ApiServices interface will then be:
#GET("svc/topstories/v2/home.json?api-key=HiddenApiKeyJustForThisMessage")
Observable<ResultsWrapper> getResults();
That is what "Expected BEGIN_ARRAY but was BEGIN_OBJECT" says to you.

Expected BEGIN_ARRAY but was BEGIN_OBJECT retrofit2

I have some problem about retrofit2
How to fix Expected BEGIN_ARRAY but was BEGIN_OBJECT in retrofit2
I don't know to fix it
What's my wrong ?
my json is
{
"result": true,
"message": "success",
"data": [
{
"id": "10",
"type_name": "pppppp"
},
{
"id_mt": "11",
"type_name": "aaaaaa"
}
]
}
and my model class is
public class MessageFastModel {
private boolean result;
private String message;
private List<DataBean> data;
public boolean isResult() {
return result;
}
public void setResult(boolean result) {
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<DataBean> getData() {
return data;
}
public void setData(List<DataBean> data) {
this.data = data;
}
public static class DataBean {
private String id;
private String type_name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType_name() {
return type_name;
}
public void setType_name(String type_name) {
this.type_name = type_name;
}
}
}
My code is
#FormUrlEncoded
#POST("api/message_type")
Call<MessageFastModel> listMessageFast(#Field("token") String token);
and
Call<MessageFastModel> dddddCall = ooooo.listMessageFast(Preferences.getToken());
dddddCall.enqueue(new Callback<MessageFastModel>() {
#Override
public void onResponse(Call<MessageFastModel> call, Response<MessageFastModel> response) {
if (response.isSuccessful()) {
Log.d("ddd", "onResponse: " + response.body().getData().size());
}
}
#Override
public void onFailure(Call<MessageFastModel> call, Throwable t) {
Log.e("ddd", "onFailure: " + t.getMessage());
}
});
but My error is
E/ddd: onFailure: java.lang.IllegalStateException: Expected
BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 44 path $.data
what's problem ? thanks!
#GET("photos")
Call<Model> savePhoto();
And Call your retrofit method like this >>>
Call<Model> call = apiService.savePhoto();
call.enqueue(new retrofit2.Callback<Model>() {
#Override
public void onResponse(Call<Model> call, retrofit2.Response<Model> response) {
int statusCode = response.code();
try {
Model model;
// Log.w("resedatasync", new Gson().toJson(response));
model= response.body();
And Create Your Model Class like this
public class Model{
#SerializedName("ArrayName")
public List<DataBean > arraylist= new ArrayList<>();
#SerializedName("message")
private String message;
public class DataBean {
#SerializedName("id")
private String id;
#SerializedName("typename")
private String typename;
#SerializedName("typename")
public void settypename(String typename) {
this.typename= typename;
}
}
}
When you have problem
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 44 path $.data
We must know that where need JSONArray .You have List<DataBean> data .So your data must use JSONArray .
And may be your problem at
Log.d("ddd", "onResponse: " + response.body().getData().size());
You can do like this .
System.out.println(response.body().string());
And show your message .
And try this class .
public class MessageFastModel {
private boolean result;
private String message;
private DataBean data;
public boolean isResult() {
return result;
}
public void setResult(boolean result) {
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public static class DataBean {
private String id;
private String type_name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType_name() {
return type_name;
}
public void setType_name(String type_name) {
this.type_name = type_name;
}
}
}
And remove Log.d("ddd", "onResponse: " + response.body().getData().size());
This happens when the structure of JSON doesn't matches with the structure of your recipient model class. Also use #Expose and #SerializedName("receivingJsonVariableName") for each variable in the model class.

Object become null when converted to json

Here is the problem, when I send my object to server using retrofit I got it null. I'm doing this to create the json object:
HashMap<String, UserModel> map = new HashMap<>();
map.put("user", user);
But, when the json arrives in the server I got something like this:
{"user":null}
Then I printed ny json file with this line:
Log.d("TAG", new JSONObject(map).toString());
And I saw the same null object.
So, here is my question, Why is this happening? And how can I fix that?
Here goes some information about my project:
Retrofit version: 2.0.0
Retrofit serializer: jackson version 2.0.0
using also jackson to convert JodaTime version 2.4.0
here goes how I get retrofit instance:
public T buildServiceInstance(Class<T> clazz){
return new Retrofit.Builder().baseUrl(BuildConfig.API_HOST)
.addConverterFactory(JacksonConverterFactory.create())
.build().create(clazz);
}
I call that method here:
public static final IUserApi serviceInstance = new ApiBuildRequester<IUserApi>()
.buildServiceInstance(IUserApi.class);
Method declaration on interface IUserApi:
#POST("User.svc/Save")
Call<ResponseSaveUserApiModel> save(#Body HashMap<String, UserModel> map);
And at last, but I guess, not less important:
public class UserModel implements Parcelable {
private String idUser;
private String name;
private String email;
#JsonProperty("password")
private String safePassword;
private String salt;
private String phoneNumber;
private String facebookProfilePictureUrl;
private String facebookUserId;
public UserModel() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdUser() {
return idUser;
}
public void setIdUser(String idUser) {
this.idUser = idUser;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getSafePassword() {
return safePassword;
}
public void setSafePassword(String safePassword) {
this.safePassword = safePassword;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getFacebookProfilePictureUrl() {
return facebookProfilePictureUrl;
}
public void setFacebookProfilePictureUrl(String facebookProfilePictureUrl) {
this.facebookProfilePictureUrl = facebookProfilePictureUrl;
}
public String getFacebookUserId() {
return facebookUserId;
}
public void setFacebookUserId(String facebookUserId) {
this.facebookUserId = facebookUserId;
}
#Override
public int describeContents() {
return 0;
}
public UserModel(Parcel in) { // Deve estar na mesma ordem do "writeToParcel"
setIdUser(in.readString());
setName(in.readString());
setEmail(in.readString());
setSafePassword(in.readString());
setPhoneNumber(in.readString());
setFacebookProfilePictureUrl(in.readString());
setFacebookUserId(in.readString());
}
#Override
public void writeToParcel(Parcel dest, int flags) { //Deve estar na mesma ordem do construtor que recebe parcel
dest.writeString(idUser);
dest.writeString(name);
dest.writeString(email);
dest.writeString(safePassword);
dest.writeString(phoneNumber);
dest.writeString(facebookProfilePictureUrl);
dest.writeString(facebookUserId);
}
public static final Parcelable.Creator<UserModel> CREATOR = new Parcelable.Creator<UserModel>(){
#Override
public UserModel createFromParcel(Parcel source) {
return new UserModel(source);
}
#Override
public UserModel[] newArray(int size) {
return new UserModel[size];
}
};
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
}
Debug screen:
#Selvin and #cricket_007 You are the best!
I got this using your hint that my printing was wrong, and I found the solution.
I have two types of users in my app, facebook users or native users, two forms, but just one object, and here was the problem, when I sent facebook objects (complete) it worked fine, but when I tried to send native users, with some null properties, it crashed my serialization.
So I had to check every property before send it, it's just a workaround, but for now it's enough, thank you a lot folks!

Creating model for select component with multidimensional enum in Tapestry

In my page class:
public SelectModel getCountryListEnum() {
return new EnumSelectModel(CountryListEnum.class, resources.getMessages());
}
public CountryListEnumEncoder getCountryListEnumEncoder(){
return new CountryListEnumEncoder();
}
In my template (select.selectcountries extends Tapestry Select Component btw):
<t:select.selectcountries id="country" t:id="country" model="CountryListEnum" value="user.address.countrycode" encoder="CountryListEnumEncoder"/>
my enum:
public enum CountryListEnum {
AFGHANISTAN("Afghanistan", "AF"),
ALBANIA("Albania", "AL"),
ALGERIA("Algeria", "DZ"),
(...ETC);
private String country;
private String code;
private CountryListEnum( String country, String code) {
this.country = country;
this.code = code;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getId() {
return getCode();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
private CountryListEnum() {
}
public static int getSize() {
return values().length;
}
public static String getNameFromCode(String code) {
for (CountryListEnum countryEnum : values()) {
if (code.trim().equals(countryEnum.getCode())) {
return countryEnum.getCountry();
}
}
throw new IllegalArgumentException("Country Code: "+ code + " does not exist");
}
}
My ValueEncoder:
public class CountryListEnumEncoder implements ValueEncoder<CountryListEnum>, ValueEncoderFactory<CountryListEnum> {
#Override
public String toClient(CountryListEnum value) {
return value.getId();
}
#Override
public CountryListEnum toValue(String clientValue) {
Validate.notEmpty(clientValue);
for (CountryListEnum countryEnum : CountryListEnum.values()) {
if (clientValue.trim().equals(countryEnum.getCode())) {
return countryEnum;
}
}
throw new IllegalArgumentException("Country Code: " + clientValue + " does not exist");
}
#Override
public ValueEncoder<CountryListEnum> create(Class<CountryListEnum> type) {
return this; //To change body of implemented methods use File | Settings | File Templates.
}
}
Finaly, I am getting the following error:
java.lang.String cannot be cast to
com.starpoint.instihire.api.domain.reference.CountryListEnum
I tried committing a type coercer (as suggested here) but that didn't work either. I also tried omitting the model param from the select and changing the id of the select.selectcountries component to a countryListEnum (as suggested here). Scratching my head on this one...
Looks like user.address.countrycode is a String and not a CountryListEnum

Categories