I have a java program which should serialize objects using jackson (play framework). It was working, but I messed it up somehow and now I can't get it working. Here is my serializer
public String serializeObject(Object object) {
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = null;
try {
json = ow.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return json;
}
and here is the code which runs it:
return badRequest(serializeObject(new Error("bad input")));
and the error class:
public class Error {
private String error;
public Error(String error) {
this.error = error;
}
}
and as the output, all I get is { }
What is wrong?
Your Error Class's properties need to have setter and getters which you want to show in JSON output
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
Related
Very new so bear with me.
The method BloodPressure() is called in MainActivity and the values are fetched and "put" into the jsonObject.
Method getBloodPressure() will return this jsonobject and is called in another module.
The jsonobject in getBloodPressure() is always empty {}.
I have try to debug. So I can see the json is created exactly. But when I "return jsonObject" in getBloodPressure it just resets and becomes {}.
How do I call the jsonObject with bloodPressure values?
MainActivity
private static void dumpDataSet(DataSet dataSet) {
.
.
.
healthdata.BloodPressure(type, systolic, diastolic, sdate, edate );
//printed this and it works perfectly fine
}
HealthData.java
public class HealthData {
private String steps,heartRate,systolic, diastolic, bloodGlucose,bodyTemperature,age, startDate, endDate, dataType;
JSONObject jsonObject = new JSONObject();
public HealthData(){
super();
}
public void BloodPressure(String type, String sys, String dia, String sdate, String edate) {
dataType = type;
systolic = sys;
diastolic = dia;
startDate = sdate;
endDate = edate;
try {
jsonObject.put("dataType", dataType);
jsonObject.put("SystolicValue", systolic);
jsonObject.put("DiastolicValue", diastolic);
jsonObject.put("startDate", startDate);
jsonObject.put("endDate", endDate);
Log.v("json:", String.valueOf(this.jsonObject)); //prints json successfully
} catch (Exception e) {
Log.v(e.toString(), null);
}
}
public JSONObject getBloodPressure() throws JSONException {
return jsonObject; //trying to return json but its empty
}
}
AnotherModule:
public void getHealthData(Callback cb) {
try {
HealthData healthData = new HealthData();
JSONObject json = healthData.getBloodPressure(); ///calling it here
cb.invoke(null, json);
} catch (Exception e){
cb.invoke(e.toString(), null);
}
}
I saw your code and found you didn't call BloodPressure() method before getBloodPressure().
I think that you should call BloodPressure() method before getBloodPressure()
So your another module code like this.
public void getHealthData(Callback cb) {
try{
HealthData healthData = new HealthData();
healthData.BloodPressure("type", "sys", "dia", "sdate", "edate") // you must call this method.
JSONObject json = healthData.getBloodPressure(); ///calling it here
cb.invoke(null, json);
} catch (Exception e) {
cb.invoke(e.toString(), null);
}
}
Update:
I think you should not create new instance of HealthData in getHealthData() method.
public void getHealthData(Callback cb) {
try{
//HealthData healthData = new HealthData(); // this line is wrong. So I removed this line.
JSONObject json = healthData.getBloodPressure(); ///calling it here
cb.invoke(null, json);
} catch (Exception e) {
cb.invoke(e.toString(), null);
}
}
I want to parse time from
<monday>
<item>
<time>00:00:00</time>
</item>
...
</monday>
as long
I defiend items as
#Root(strict = false)
private static class Item {
#Element(name = "time")
#Convert(TimeConverter.class)
private Long time;
}
My Converter
public class TimeConverter implements org.simpleframework.xml.convert.Converter<Long> {
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
#Override
public Long read(InputNode node) throws Exception {
try {
String value = node.getValue();
return df.parse(value).getTime();
} catch (Exception e) {
Log.e("mcheck", "read: ", e);
return 0L;
}
}
#Override
public void write(OutputNode node, Long value) throws Exception {
try {
String v = df.format(new Date(value));
node.setValue(v);
} catch (Exception e) {
Log.e("mcheck", "write: ", e);
}
}
}
However when I parse it I receive
retrofit.RetrofitError: java.lang.NumberFormatException: Invalid long: "00:00:00"
As this exception is not caught in my try-catch blocks in converter I assume that parser does not visit converter at all.
My retrofit 1.9 call
OkHttpClient httpClient = new OkHttpClient();
RestAdapter.Builder builder = new RestAdapter.Builder();
builder.setEndpoint(url);
builder.setLogLevel(RestAdapter.LogLevel.FULL);
builder.setConverter(new SimpleXMLConverter());
builder.setClient(new OkClient(httpClient));
RestAdapter restAdapter = builder.build();
ChansonApi api = restAdapter.create(ChansonApi.class);
api.getStreamProgram(new Callback<StreamProgram>() {
#Override
public void success(StreamProgram streamProgram, Response response) {
if(streamProgram!=null){
Log.e("mcheck", "success: "+streamProgram.getProgram());
}
}
#Override
public void failure(RetrofitError error) {
Log.e("mcheck", "failure: ",error);
}
});
The problem was in proguard settings. I had to add TimeConverter to -keep class list
I'm currently using a JSON Schema Validator in conjunction with Gson to handle exceptions and validate json requests made to an API.
The validator can return multiple exceptions when comparing a request with a schema. The sample from the repository is:
try {
schema.validate(rectangleMultipleFailures);
}
catch (ValidationException e) {
System.out.println(e.getMessage());
e.getCausingExceptions().stream()
.map(ValidationException::getMessage)
.forEach(System.out::println);
}
And my implementation of the try catch (missing the catch obviously) is:
try (InputStream inputStream = this.getClass().getResourceAsStream("SupplierSchemaIncoming.json")) {
JSONObject rawSchema = new JSONObject(new JSONTokener(inputStream));
Schema schema = SchemaLoader.load(rawSchema);
// Throws a ValidationException if requestJson is invalid:
schema.validate(new JSONObject(requestJson));
}
catch (ValidationException ve) {
System.out.println(ve.toJSON().toString());
}
As you can see above, one option is to return all of the errors as a single JSON.
{
"pointerToViolation": "#",
"causingExceptions": [{
"pointerToViolation": "#/name",
"keyword": "type",
"message": "expected type: String, found: Integer"
}, {
"pointerToViolation": "#/type",
"keyword": "type",
"message": "expected type: String, found: Integer"
}],
"message": "2 schema violations found"
}
However, I'm stumped on how to get the exception to return an array of SchemaError objects (below) which I can parse however I want.
package domainObjects;
import com.google.gson.annotations.Expose;
public class SchemaError {
#Expose
String pointerToViolation;
#Expose
String keyword;
#Expose
String message;
public SchemaError() {}
public String getPointerToViolation() {
return pointerToViolation;
}
public void setPointerToViolation(String pointerToViolation) {
this.pointerToViolation = pointerToViolation;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Found another answer which recommended serialising the object from a JSONObject to a JSONElement and returning that. The catch() now has:
catch (ValidationException ve) {
JSONObject jsonObject = ve.toJSON();
Gson gson = new Gson();
JsonElement element = gson.fromJson(jsonObject.toString(), JsonElement.class);
return element;
}
I want to deserialize a JSON response but I'm not sure about the format. The format can vary in each case. For example the response contains a field named "error" which may be false (boolean) or an object that describes the error eg. "error": { "code": xxx , "description":"etc"}
How should I implement a class that covers both cases? Is there any way to do this?
Thanks
I would prefer using a TypeAdapter for your case:
private static class Error {
private boolean hasError;
private int code;
private String description;
}
private static class ErrorTypeAdapter extends TypeAdapter<Error> {
#Override
public Error read(JsonReader jsonReader) throws IOException {
Error response = null;
jsonReader.beginObject();
while (jsonReader.hasNext()) {
String currentJsonName = jsonReader.nextName();
if("error".equals(currentJsonName)) {
response = new Error();
try {
response.hasError = jsonReader.nextBoolean();
} catch (Exception e) {
response.hasError = true;
jsonReader.beginObject();
}
} else if("code".equals(currentJsonName)) {
response.code = jsonReader.nextInt();
} else if ("description".equals(currentJsonName)) {
response.description = jsonReader.nextString();
}
}
if(response.hasError) {
jsonReader.endObject();
}
jsonReader.endObject();
return response;
}
#Override
public void write(JsonWriter jsonWriter, Error response)
throws IOException {
jsonWriter.beginObject();
jsonWriter.name("hasError").value(response.hasError);
jsonWriter.name("code").value(response.code);
jsonWriter.name("description").value(response.description);
jsonWriter.endObject();
}
}
To test it you can use:
String val1 = "{\"error\": {\"code\": 1 , \"description\":\"etc\"}}";
String val2 = "{\"error\": false}";
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Error.class, new ErrorTypeAdapter());
gsonBuilder.setPrettyPrinting();
final Gson gson = gsonBuilder.create();
gson.fromJson(val1, Error.class);
gson.fromJson(val2, Error.class);
You can read more about TypeAdapters here and also some great examples here.
I am facing a bizarre situation while parsing a json string using readValue() of ObjectMaper. I am using Jackson 2.4.1 along with Spring 4.0.6.
Problem is, same json string when fed to readValue() gives null at times and other times valid object.
JSON String :
{"productGroupInfoTransport": {"groupId":36,"range":"LMEURSMA","productType":"LMFE","status":"ANNOUNCE","regionsList":[],"productsList":[],"groupName":"Bright Start test"}}
Code:
public Object getData(String jSONObject, String action, String module)
throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
mapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES,
false);
mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,
false);
//mapper.configure(SerializationConfig. WRITE_NULL_PROPERTIES, false);
String transport = null;
if (jSONObject.contains(ERROR)) {
transport = "Exception";
throw new Exception("Unable to read Data");
} else {
transport = getTransport(action, module);
}
Object transportObject = null;
transportObject = mapper.readValue(jSONObject, getTransport(transport));
return transportObject;
}
ProductTransport :
package com.leggmason.lmEPAM.transport;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.leggmason.lmEPAM.model.ProductGroupModel;
public class ProductGroupTransport extends EPAMTransport<ProductGroupModel> {
#JsonProperty("productGroupInfoTransport")
protected ProductGroupModel modelObject;
#JsonProperty("productGroupTransport")
protected List<ProductGroupModel> data;
#JsonProperty("productGroupTransport")
#Override
public List<ProductGroupModel> getListData() {
return this.data;
}
#JsonProperty("productGroupTransport")
#Override
public void setData(List<ProductGroupModel> data) {
this.data = (List<ProductGroupModel>) data;
}
#Override
public String getModule() {
return null;
}
#JsonProperty("productGroupInfoTransport")
#Override
public ProductGroupModel getObject() {
return this.modelObject;
}
#JsonProperty("productGroupInfoTransport")
public void setObject(ProductGroupModel modelObject) {
this.modelObject = modelObject;
}
#Override
public void setObject(Object modelObject) {
// TODO Auto-generated method stub
}
}
In above code when JsonString is passed, one time ProductTransposrt will have its modelObject populated correctly with Object but as I restart the server, same JSON string will give modelObject as null after parsing. I fail to understand why. Thanks for help.
You can try following code for parsing json object
JSONObject obj = new JSONObject(jSONObject);
JSONArray array = obj.getJSONArray("productGroupInfoTransport");
System.out.println(array.getJSONObject(0).getString("groupId"))
Now you can parse json string properly.
It may be help for only parsing json string.