I am using JsonObject and Gson to format the data i need to send in the form of String and then retrieve and parse it somewhere else.
This is my simple code which is not working:
public static void main(String[] args)
{
Gson g = new Gson();
Gson listG = new Gson();
ArrayList<String> l= new ArrayList<String>();
l.add("abcd");
l.add("efgh");
l.add("ijkl");
String list = listG.toJson(l);
JsonObject jObject = new JsonObject();
jObject.addProperty("command" , 1);
jObject.addProperty("message" , "this is a test message");
jObject.addProperty("list" , list);
String toSend = g.toJson(jObject);
System.out.println(toSend);
Gson rec = new Gson();
JsonObject newObj = rec.fromJson(toSend, JsonObject.class);
System.out.println(newObj); // getting nothing in newObj
}
What am i doing wrong here?
You should use:
JsonObject newObj = new JsonParser().parse(toSend).getAsJsonObject();
Lots of calls in there, but the gist is to use the JsonParser class.
Related
I am new to testing and i am trying to write a unit test cases on a Flink Datastream which takes input a jsonobject and passes the json object to a processfuntion and it returns a valid or invalid jsonobject when certain rule conditions are met below is the junit test case, below i am trying to compare the output jsonobject from process function with the jsonobject of the input file
#Test
public void testcompareInputAndOutputDataJSONSignal() throws Exception {
org.json.JSONObject jsonObject = toJsonObject();
String input = jsonObject.toString();
String output = JSONDataStreamOutput();
assertEquals(mapper.readTree(input), mapper.readTree(output));
}
below is my toJSONObject and JSONDataStream meathods
public static JSONObject toJsonObject() throws IOException, ParseException {
JSONParser jsonParser = new JSONParser();
FileReader fileReader = new FileReader(getFileFromResources("input.json"));
JSONObject obj = (JSONObject) jsonParser.parse(fileReader);
return obj;
}
public String SignalDataStreamOutput() throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
DataStream<JSONObject> validSignal = env.fromElements(toJsonObject())
.process(new JsonFilter());
String outputFolder = "output";
validSignal.writeAsText(outputFolder).setParallelism(1);
env.execute();
String content = new String(Files.readAllBytes(Paths.get("output.txt")));
return content;
}
What i am doing is i am converting a jsonfile to jsonobject using the toJSONObject method and sending to a data stream using SignalDataStreamOutput method which will intern send it to a process function in JsonFilter class and validate it against a set of rules and if it's valid it will return a jsonobject and when trying to access the jsonobject directly from stream i am getting value like org.apache.flink#994jdkeiri so i am trying to write the output to a file and trying to read it back to a string and comparing it in test method but this is a work around process and i found a link to use Mockito framework here i changed it to use json object like below
final Collector<JSONObject> collectorMock = (Collector<JSONObject>)Mockito.mock(JsonFilter.class);
final Context contextMock = Mockito.mock(Context.class);
#Test
public void testcompareInputAndOutputDataForValidSignal() throws Exception {
org.json.JSONObject jsonObject = convertToJsonObject();
Mockito.verify(collectorMock).collect(jsonObject);
}
but the above approach is also not working can you suggest me simplified approach to test the json object
I can't seem to find out how to serialize Hibernate's implementation of constraint violations using Gson.
Here's what I've tried so far.
Approach 1
MyPojo aPojo = new MyPojo();
Gson gson = new Gson();
Set<ConstraintViolation<MyPojo>> violations = validator.validate(aPojo);
System.out.println(gson.toJson(violations));
Fails with this error:
java.lang.UnsupportedOperationException:
Attempted to serialize java.lang.Class: com.bar.baz.MyPojo.
Forgot to register a type adapter?
at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:67)
at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.ObjectTypeAdapter.write(ObjectTypeAdapter.java:107)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
at com.google.gson.Gson.toJson(Gson.java:593)
at com.google.gson.Gson.toJson(Gson.java:572)
at com.google.gson.Gson.toJson(Gson.java:527)
at com.google.gson.Gson.toJson(Gson.java:507)
Approach 2
Gson gson = new Gson();
Set<ConstraintViolation<MyPojo>> violations = validator.validate(MyPojo);
System.out.println(
gson.toJson(violations,
new TypeToken<ConstraintViolation<MyPojo>>() {}.getType())
);
Fails by not serializing MyPojo's properties:
Output: {}.
Approach 3
I was expecting this approach to delegate serialization to my custom Serializer but it still fails:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(
new TypeToken<ConstraintViolation<MyPojo>>() {}.getType(),
new JsonSerializer<ConstraintViolation<MyPojo>>() {
#Override
public JsonElement serialize(ConstraintViolation<MyPojo> src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
result.addProperty("aTestProperty", "A Test Value");
return result;
}
});
Gson gson = builder.create();
Set<ConstraintViolation<MyPojo>> violations = validator.validate(MyPojo);
System.out.println(gson.toJson(violations));
However it fails with this error:
java.lang.UnsupportedOperationException:
Attempted to serialize java.lang.Class:
com.bar.baz.MyPojo.
Forgot to register a type adapter?
at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:67)
at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.ObjectTypeAdapter.write(ObjectTypeAdapter.java:107)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
at com.google.gson.Gson.toJson(Gson.java:593)
at com.google.gson.Gson.toJson(Gson.java:572)
at com.google.gson.Gson.toJson(Gson.java:527)
at com.google.gson.Gson.toJson(Gson.java:507)
Approach 4
Looking at the error message, I though this might work:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(
new TypeToken<ConstraintViolation<MyPojo>>() {}.getType(),
new JsonSerializer<ConstraintViolation<MyPojo>>() {
#Override
public JsonElement serialize(ConstraintViolation<MyPojo> src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
result.addProperty("aTestProperty", "A Test Value");
return result;
}
});
builder.registerTypeAdapter(
new TypeToken<MyPojo>() {}.getType(),
new JsonSerializer<MyPojo>() {
#Override
public JsonElement serialize(MyPojo src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
result.addProperty("anotherTestProperty", "Another Test Value");
return result;
}
});
Gson gson = builder.create();
Set<ConstraintViolation<MyPojo>> violations = validator.validate(MyPojo);
System.out.println(gson.toJson(violations));
But it fails with a similar error.
Approach 5: Working but ugly
The only thing that I've managed to make work is to register the serializer with the type of the vendor (Hibernate) specific implementation for ConstraintViolation:
Set<ConstraintViolation<MyPojo>> violations = validator.validate(MyPojo);
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(
new TypeToken<ConstraintViolationImpl>() {}.getType(),
new JsonSerializer<ConstraintViolation<MyPojo>>() {
#Override
public JsonElement serialize(ConstraintViolation<MyPojo> src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();
result.addProperty("aTestProperty", "A Test Value");
return result;
}
});
Gson gson = builder.create();
System.out.println(gson.toJson(violations));
Is there a way to make this work without relying on the concrete implementation of ConstraintViolation (i.e. org.hibernate.validator.internal.engine.ConstraintViolationImpl)?
There doesn't seem to be a reasonable approach to serialize javax.validation.ConstraintViolation objects. In fact, even Jackson errs while trying to serialize the set:
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: fromIndex(0) > toIndex(-1) (through reference chain: java.util.HashSet[0]->org.hibernate.validator.internal.engine.ConstraintViolationImpl["propertyPath"]->org.hibernate.validator.internal.engine.path.PathImpl["pathWithoutLeafNode"]->org.hibernate.validator.internal.engine.path.PathImpl["pathWithoutLeafNode"]->org.hibernate.validator.internal.engine.path.PathImpl["pathWithoutLeafNode"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)
For the time being, I just convert the set of errors into a set of custom POJOs I've written and serialize that instead.
Custom ValidationError POJO:
public class ValidationError {
private String className;
private String propertyPath;
private String errorMessage;
public static Set<ValidationError> fromViolations(Set violations) {
Set<ValidationError> errors = new HashSet<ValidationError>();
for (Object o : violations) {
ConstraintViolation v = (ConstraintViolation) o;
ValidationError error = new ValidationError();
error.setClassName(v.getRootBeanClass().getSimpleName());
error.setErrorMessage(v.getMessage());
error.setPropertyPath(v.getPropertyPath().toString());
errors.add(error);
}
return errors;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getPropertyPath() {
return propertyPath;
}
public void setPropertyPath(String propertyPath) {
this.propertyPath = propertyPath;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
#Override
public String toString() {
return "ValidationError{" +
"className='" + className + '\'' +
", propertyPath='" + propertyPath + '\'' +
", errorMessage='" + errorMessage + '\'' +
'}';
}
}
Sample usage:
Set<ConstraintViolation<MyBean>> violations = validator.validate(myBean);
Set<ValidationError> errors = ValidationError.fromViolations(violations);
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
System.out.println(gson.toJson(errors));
Update
For the sake of record, it is worth mentioning that XStream can serialize the set of constraint violations like a charm:
XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.setMode(XStream.NO_REFERENCES);
System.out.println(xstream.toXML(violations));
However the generated the object graph is way too much verbose and is not suitable for use in production anyway. You can see the sample output here.
I have a Json file E:\\jsondemo.json in disk. I want to create JSONObject in Java and add the contents of the json file to JSONObject. How it is possible?
JSONObject jsonObject = new JSONObject();
After creating this objec, what should i do to read the file and put values in jsonObject
Thanks.
You can transform a file in a String using a function proposed in this question:
private static String readFile(String path) throws IOException {
FileInputStream stream = new FileInputStream(new File(path));
try {
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
/* Instead of using default, pass in a decoder. */
return Charset.defaultCharset().decode(bb).toString();
}
finally {
stream.close();
}
}
After getting the string, you can transform it to a JSONObject with the following code:
String json = readFile("E:\\jsondemo.json");
JSONObject jo = null;
try {
jo = new JSONObject(json);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
In the above example, I used this library, very simple to learn. You can add values to your JSON object in this way:
jo.put("one", 1);
jo.put("two", 2);
jo.put("three", 3);
You can also create JSONArray objects, and add it to your JSONObject:
JSONArray ja = new JSONArray();
ja.put("1");
ja.put("2");
ja.put("3");
jo.put("myArray", ja);
use the org.json.jar
I know convert a JSON code to JSONObject
JSONObject fieldsJson = new JSONObject("{\"a\":\"b\"}");
String value= fieldsJson.getString("a");
But how to convert a JSON code to map
String str = "{\"age\":\"23\",\"name\":\"ganlu\"}";
JSONObject jobj = JSONObject.fromObject(str);
Map<String,String> tmpMap = (Map) JSONObject.toBean(jobj,Map.class);
Set<String> keys = tmpMap.keySet();
for(String key : keys){
System.out.println(key+":"+tmpMap.get(key));
}
May this will help you.
sorry for the silly question, but i am stuck converting for example the following result from a method into Json
public string Test(string input) {
return "Name:" + input;
}
to look like this
{"Name":"Mike"}
Update:
Darin fixed first problem now i am using this way but it is not working
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using(JsonWriter jsonWriter = new JsonTextWriter(sw)) {
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.WritePropertyName("Name");
jsonWriter.WriteValue("Mike");
}
I get
'{"Name":{"m_MaxCapacity":2147483647,"Capacity":16,"m_StringValue":"\\"Name\\": \\"Mike\\"","m_currentThread":0}}';
You could use the JavaScriptSerializer class:
public string Test(string input)
{
var serializer = new JavaScriptSerializer();
return serializer.Serialize(new { Name = input });
}
Example usage:
string json = Test("Mike"); // json = {"Name":"Mike"}
UPDATE:
Didn't notice you wanted a solution using the Json.NET library. Here's one:
string json = JsonConvert.SerializeObject(new { Name = input });