So i am using Jackson to convert objects to JSON and then send them over a connection and convert them back to objects on the other side of the connection. I ran into a problem when reading the JSON and attempting to turn it into a JAVA object it successfully changes JSON into multiple objects. It is easier to see in an example:
ObjectMapper map = new ObjectMapper();
Boolean test1 = null;
String test2 = null;
Integer test3 = null;
Boolean obj = false;
byte[] bytes = null;
try {
bytes = map.writeValueAsBytes(obj);
} catch (Exception e) {
e.printStackTrace();
}
try {
test1 = map.readValue(bytes, Boolean.class);
test2 = map.readValue(bytes, String.class);
test3 = map.readValue(bytes, Integer.class);
} catch (Exception e)
{
System.out.println("FAILED");
}
System.out.println("test1: " + test1 + "\ntest2: " + test2 + "\ntest3: " + test3);
And the output:
FAILED
test1: false
test2: false
test3: null
When attempting to convert the JSON Boolean to a String it was successful which is problematic for me because my current method looks similar to what is below and when the object deserialize is of the wrong type it causes problems down the road.
public void JSONtoJAVA(Class<?> clazz)
{
for(Event event : Events)
{
try
{
Object deserialized = map.readValue(bytes, event.getC());
Event.getMethod().invoke(deserialized);
}
catch(Exception e)
{
//Failed ignore
}
}
}
Your help is appreciated!
Related
public KustoResultSetTable executeKustoQuery(ClientImpl client, String query) {
KustoResultSetTable mainTableResult = null;
try {
KustoOperationResult results = client.execute(databaseName, query);
mainTableResult = results.getPrimaryResults();
} catch (DataServiceException | DataClientException e) {
errorHandler(e, "Error while retrieving results from kusto query!");
}
return mainTableResult;
}
The above code returns me a result of this type
Name | Age
XYZ AAA | 29
How can I get the value of 1st row under name column using Azure Kusto Java mainTableResult object
Expected String output - "XYZ AAA"
You can do:
if (mainTableResult.first()) {
int columnIndex = mainTableResult.findColumn("Name")
return mainTableResult.getString(columnIndex);
} else {
throw new UnsupportedOperationException(""); // Or any other error handling
}
A complete version is:
public String executeKustoQuery(ClientImpl client, String query) {
KustoResultSetTable mainTableResult = null;
try {
KustoOperationResult results = client.execute("databaseName", query);
mainTableResult = results.getPrimaryResults();
if (mainTableResult.first()) {
int columnIndex = mainTableResult.findColumn("Name")
return mainTableResult.getString(columnIndex);
} else {
throw new UnsupportedOperationException(""); // Or any other error handling
}
} catch (DataServiceException | DataClientException e) {
errorHandler(e, "Error while retrieving results from kusto query!");
}
}
I'm parsing a JSON string by using Gson and Retrofit. I have this JSON string:
{"message":["Email has already been taken"]}
I get the below exception still and don't know why:
java.io.EOFException: End of input at line 1 column 1 path $
at com.google.gson.stream.JsonReader.nextNonWhitespace(JsonReader.java:1393)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:549)
at com.google.gson.stream.JsonReader.peek(JsonReader.java:425)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:205)
at com.google.gson.TypeAdapter.fromJson(TypeAdapter.java:260)
at com.google.gson.TypeAdapter.fromJson(TypeAdapter.java:273)
People who know how to get the value of message field please help me.
BaseApiDto.java
public class BaseApiDto {
#SerializedName("message")
public String[] message;
public String getError() {
return message[0];
}
}
HandErrorUtils.java
public static void handleError(FragmentActivity activity, Throwable e) {
String msg = null;
if(e instanceof HttpException){
// Error message in json
Gson gson = new Gson();
TypeAdapter<BaseApiDto> adapter = gson.getAdapter(BaseApiDto.class);
ResponseBody body = ((HttpException) e).response().errorBody();
// Status code
HttpException httpException = (HttpException) e;
int statusCode = httpException.code();
if (statusCode == 500) {
showErrorDialog(activity, activity.getString(R.string.dialog_msg_error_401), true);
} else if (statusCode == 401) {
showErrorDialog(activity, activity.getString(R.string.dialog_msg_error_401), true);
} else {
try {
Timber.w("body.string() " + body.string());
// TODO : EXCEPTION HAPPEN IN HERE
BaseApiDto errorDto = adapter.fromJson(body.string());
msg = errorDto.getError();
Timber.w("msg " + msg);
} catch (Exception ex) {
// TODO : EXCEPTION HAPPEN IN HERE
ex.printStackTrace();
}
showErrorDialog(activity, msg, false);
}
}
}
UPDATE I assign body.toString() to variable, somehow it worked.
String response = body.string();
BaseApiDto errorDto = adapter.fromJson(response);
It worked because I didn't call body.string() twice.
I assign body.toString() to variable, somehow it worked.
String response = body.string();
BaseApiDto errorDto = adapter.fromJson(response);
I am currently writing test cases using TestNg. I populate objects using PodamFactory. I have following test case structure.
#Test
public void testIt(){
ARespObject resp = PodamFactory.manufacturePojo(ARespObject.class);
String responseXml = new JaxbStringTransformer().transform(resp);
// a new object with all the same data
ARespObject respActual = responder.getObj(responseXml);
Assert.assertTrue(TestUtils.areEqual(respActual , resp));
}
public static <T extends Object> boolean areEqual(T sourceObj, T target) {
if (sourceObj == null && target == null) {
return true;
}
if (sourceObj == target) {
return true;
}
if (sourceObj.getClass() != target.getClass()) {
return false;
}
if (sourceObj != null && target != null) {
return stringifyObject(sourceObj).equals(stringifyObject(target));
}
return false;
}
public static String stringifyObject(Object obj) {
String result = "";
ObjectWriter ow = new JaxbJacksonObjectMapper().writer().withDefaultPrettyPrinter();
try {
result = ow.writeValueAsString(obj);
} catch (JsonGenerationException e1) {
LOG.error(e1);
} catch (JsonMappingException e1) {
LOG.error("JsonMappingException: " + e1);
} catch (IOException e1) {
LOG.error("IOException: " + e1);
}
return result;
}
I need to know if writeValueAsString(obj) will always provide same structure for both objects(i.e. its output will be stable) and following
stringifyObject(sourceObj).equals(stringifyObject(target));
is a valid check. I am concerned about whether it will ever give me different ordering of variables inside the ARespObject.
Rather than formatting the objects to strings for comparison, convert them to "tree model" (JsonNode implementations). ObjectNode implements equals/hashCode/toString etc to reasonably imitate JSON equivalence, so it will disregard the order of properties for example.
ObjectMapper mapper = new ObjectMapper();
JsonNode treeNode = mapper.convertValue(obj, JsonNode.class);
(typically you will actually get an ObjectNode back, but you can just probably just use the JsonNode interface)
The tree model classes will also perform a simple JSON formatting for toString() output, so "expected" and "actual" printouts should be readable (although not as pretty as with the pretty printer)
I would recommend against using the string representation of an object to test for equality. You should instead use the .equals method of the objects you want to test.
I am trying to write an automated Java test where the code will go to a specified URL, read the JSON data and print it up.
Here is the JSON I am trying to access;
{
"status": "success",
"records": [
{
"timestamp": 1381222871868,
"deviceId": "288",
"temperature": 17
},
{
"timestamp": 1381222901868,
"deviceId": "288",
"temperature": 17
},
{
"timestamp": 1381222931868,
"deviceId": "288",
"temperature": 17
},
]}
As you can see I only have 3 elements, Timestamp, DeviceId and Temperature.
What I am ultimately aiming for it to be able to get 2 Timestamp values and take one value away from the other, if that is possible.
Anyway I have been trying to do this all day and am having no luck whatsoever. I was recommended to use Gson and I have included the jar files into my classpath.
If anyone knows anything or can help me in any way it would be much appreciated as I have exhausted Google and myself trying to work this out.
Here is the code I have to display the full list, but I do not fully understand it and so far can't manipulate it to my advantage;
public static void main(String[] args) throws Exception
{
String jsonString = callURL("http://localhost:8000/eem/api/v1/metrics/temperature/288");
System.out.println("\n\njsonString: " + jsonString);
// Replace this try catch block for all below subsequent examples
/*try
{
JSONArray jsonArray = new JSONArray(jsonString);
System.out.println("\n\njsonArray: " + jsonArray);
}
catch (JSONException e)
{
e.printStackTrace();
}*/
try
{
JSONArray jsonArray = new JSONArray(jsonString);
int count = jsonArray.length(); // get totalCount of all jsonObjects
for(int i=0 ; i< count; i++)
{ // iterate through jsonArray
JSONObject jsonObject = jsonArray.getJSONObject(i); // get jsonObject # i position
System.out.println("jsonObject " + i + ": " + jsonObject);
}
}
catch (JSONException e)
{
e.printStackTrace();
}
}
public static String callURL(String myURL)
{
//System.out.println("Requested URL:" + myURL);
StringBuilder sb = new StringBuilder();
URLConnection urlConn = null;
InputStreamReader in = null;
try
{
URL url = new URL(myURL);
urlConn = url.openConnection();
if (urlConn != null)
{
urlConn.setReadTimeout(60 * 1000);
}
if (urlConn != null && urlConn.getInputStream() != null)
{
in = new InputStreamReader(urlConn.getInputStream(),
Charset.defaultCharset());
BufferedReader bufferedReader = new BufferedReader(in);
if (bufferedReader != null)
{
int cp;
while ((cp = bufferedReader.read()) != -1)
{
sb.append((char) cp);
}
bufferedReader.close();
}
}
in.close();
}
catch (Exception e)
{
throw new RuntimeException("Exception while calling URL:"+ myURL, e);
}
return sb.toString();
}
Cheers
I had read the values from file but you can read from URL, the extracting process code is present inside extractJson() method.
public static void main(String [] args)
{
try
{
FileInputStream fis=new FileInputStream("testjson.json");
int b=0;
String val="";
while((b=fis.read())!=-1)
{
val=val+(char)b;
}
extractJson(val);
}
catch(Exception e)
{
e.printStackTrace();
}
}
public static void extractJson(String json)
{
try
{
JSONObject jobject=new JSONObject(json);
System.out.println("Json object Length: "+jobject.length());
System.out.println("Status: "+jobject.getString("status"));
JSONArray jarray=new JSONArray(jobject.getString("records"));
System.out.println("Json array Length: "+jarray.length());
for(int j=0;j<jarray.length();j++)
{
JSONObject tempObject=jarray.getJSONObject(j);
System.out.println("Timestamp: "+tempObject.getString("timestamp"));
System.out.println("Device Id: "+tempObject.getString("deviceId"));
System.out.println("Temperature: "+tempObject.getString("temperature"));
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
You could use ArrayList to store the values which will be available inside for loop. From your question you need to pass jsonString this variable to the extractJson() method. Use org.json jar file to process json. If you could alter this for gson then it'll be good for your requirement.
here's how to do it via Google-Gson
class MyRecord
{
private long timestamp;
private String deviceId;
private Integer temperature;
//Getters & setters
}
public static void main(String... args){
String myJsonString=callUrl("http://mydomain.com/x.json");
JsonParser jp = new JsonParser();
JsonElement ele = jp.parse(myJsonString);
Gson gg = new Gson();
Type type = new TypeToken<List<MyRecord>>() {
}.getType();
List<MyRecord> lst= gg.fromJson(ele.getAsJsonObject().get("records"), type);
//Now the json is parsed in a List of MyRecord, do whatever you want to with it
}
An "high-level" Gson parsing answer:
package stackoverflow.questions.q19252374;
import java.util.List;
import com.google.gson.Gson;
public class Q19252374 {
class Record {
Long timestamp;
String deviceId;
Long temperature;
}
class Container {
List<Record> records;
}
public static void main(String[] args) {
String json = "{ \"status\": \"success\", \"records\": [{\"timestamp\": 1381222871868,\"deviceId\": \"288\",\"temperature\": 17 },{\"timestamp\": 1381222901868,\"deviceId\": \"288\",\"temperature\": 17 },{\"timestamp\": 1381222931868,\"deviceId\": \"288\",\"temperature\": 17 } ]} ";
Gson g = new Gson();
Container c = g.fromJson(json, Container.class);
for (Record r : c.records)
System.out.println(r.timestamp);
}
}
Of course this is the result:
1381222871868
1381222901868
1381222931868
I'm having an issue trying to parse a string using json-simple, this is the sample string:
{
"items": [
{
"id": "uy0nALQEAM4",
"kind": "youtube#video",
"etag": "\"g-RLCMLrfPIk8n3AxYYPPliWWoo/x3SYRGDdvDsN5QOd7AYVzGOJQlM\"",
"status": {
"uploadStatus": "processed",
"privacyStatus": "public",
"license": "youtube",
"embeddable": true,
"publicStatsViewable": true
}
}
]
}
This is my code:
JSONParser parser = new JSONParser();
Object obj = parser.parse(result);
JSONObject jsonObject = (JSONObject) obj;
System.out.println("privacyStatus: "
+ (String) jsonObject.get("items[0].status.privacyStatus")
+ "\nembeddable: "
+ (String) jsonObject.get("items[0].status.embeddable")
+ "\npublicStatsViewable: "
+ (String) jsonObject.get("items[0].status.publicStatsViewable"));
The output is:
privacyStatus: null
embeddable: null
publicStatsViewable: null
What stupid mistake am I making?
I was able to get the privacyStatus this way, however I cant seem to see anything in their documentation where they show any examples of using a chained get statement like the ones you have.
((JSONObject)((JSONObject)((JSONArray) jsonObject.get("items")).get(0)).get("status")).get("privacyStatus")
Edit: I found this little snippet in some android code I have It will work with the http://json.org/java/ library (this is very similar if not the same as the android JSON library)
public static void main(String[] args)
{
// this is the same JSON string in the OP
String jsonString = "{ \"items\": [ { \"id\": \"uy0nALQEAM4\", \"kind\": \"youtube#video\", \"etag\": \"\\\"g-RLCMLrfPIk8n3AxYYPPliWWoo/x3SYRGDdvDsN5QOd7AYVzGOJQlM\\\"\", \"status\": { \"uploadStatus\":\"processed\", \"privacyStatus\": \"public\", \"license\": \"youtube\", \"embeddable\": true, \"publicStatsViewable\": true } } ]}";
JSONObject object = new JSONObject(jsonString);
try {
String myValue = (String)getJSONValue("items[0].status.privacyStatus", object);
System.out.println(myValue);
} catch (JSONException ex) {
Logger.getLogger(JavaApplication10.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static Object getJSONValue(String exp, JSONObject obj) throws JSONException {
try {
String [] expressions = exp.split("[\\.|\\[|\\]]");
Object currentObject = obj;
for(int i=0; i < expressions.length; i++) {
if(!expressions[i].trim().equals("")) {
System.out.println(expressions[i] + " " + currentObject);
if(currentObject instanceof JSONObject) {
Method method = currentObject.getClass().getDeclaredMethod("get", String.class);
currentObject = method.invoke(currentObject, expressions[i]);
} else if(currentObject instanceof JSONArray) {
Method method = currentObject.getClass().getDeclaredMethod("get", Integer.TYPE);
currentObject = method.invoke(currentObject, Integer.valueOf(expressions[i]));
} else {
throw new JSONException("Couldnt access property " + expressions[i] + " from " + currentObject.getClass().getName());
}
}
}
return currentObject;
} catch (NoSuchMethodException ex) {
throw new JSONException(ex);
} catch (IllegalAccessException ex) {
throw new JSONException(ex);
} catch (IllegalArgumentException ex) {
throw new JSONException(ex);
} catch (InvocationTargetException ex) {
throw new JSONException(ex);
}
}
I guess it's a library limitation to solve it in a clean way. I found minimal library:
https://github.com/ralfstx/minimal-json
Which is very nice and clean. Then did the following to do what I wanted:
JsonObject jsonObject = JsonObject.readFrom(result.toString())
.get("items").asArray().get(0).asObject().get("status").asObject();
Then I can do:
boolean isPublic = jsonObject.get("privacyStatus").asString().equals("public");
boolean isEmbbedable = jsonObject.get("embeddable").asBoolean();