I have a json payload with:
"host_names": [
"www.host1.com",
"www.host2.com"
]
How can I deserialize this as a csv using Jackson - e.g.:
"www.host1.com,www.host2.com"
Previously I was deserializing this as a String[] but I can't persist that with hibernate, so now I'm trying to deserialize it as a csv.
EDIT:
I want to use annotations to turn the json array into a string, where each element of the array is separated by a comma. Perhaps something like #JsonRawValue. The goal is to then persist the value to a data via hibernate.
public static void main(String[] args) {
String jsonStr = "{\"host_names\": [\r\n" +
" \"www.host1.com\",\r\n" +
" \"www.host2.com\"\r\n" +
"]}";
JSONObject jsonObject = new JSONObject(jsonStr);
JSONArray hostNames = jsonObject.getJSONArray("host_names");
String result = "";
for(int i=0;i<hostNames.length(); i++) {
if(!result.isEmpty())
result = result+",\""+hostNames.getString(i)+"\"";
else
result = "\""+hostNames.getString(i)+"\"";
}
System.out.println(result);
}
result
"www.host1.com","www.host2.com"
Other approach based on annotation
Create a class
class Server{
#JsonProperty(value = "host_names")
private List<String> hostNames;
public List<String> getHostNames() {
return hostNames;
}
public void setHostNames(List<String> hostNames) {
this.hostNames = hostNames;
}
}
Now use com.fasterxml.jackson.databind.ObjectMapper to parse the JSON into this class
public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
String jsonStr = "{\"host_names\": [\r\n" +
" \"www.host1.com\",\r\n" +
" \"www.host2.com\"\r\n" +
"]}";
ObjectMapper mapper = new ObjectMapper();
Server server = mapper.readValue(jsonStr, Server.class);
System.out.println(server.getHostNames());
}
output
[www.host1.com, www.host2.com]
You can slightly modify your setter / getter for host_names property as
Bean Class
public class Server {
#JsonProperty("host_names")
private List<String> hostNames;
#JsonGetter("host_names")
public String getHostNames() {
return String.join(",", hostNames);
}
#JsonSetter("host_names")
public void setHostNames(List<String> hostNames) {
this.hostNames = hostNames;
}
}
Main Method
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Server server = mapper.readValue("{\"host_names\":[\"www.host1.com\",\"www.host2.com\"]}", Server.class);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(server);
System.out.println(json);
}
Output
{
"host_names" : "www.host1.com,www.host2.com"
}
This way you can serialize as comma separated string, and array of string while deserializing.
Another Solution using #JsonValue Annotation.
Define your bean class as:
public class Server {
#JsonProperty("host_names")
private List<String> hostNames;
#JsonValue
public String hostNames() {
return String.join(",", hostNames);
}
public List<String> getHostNames() {
return hostNames;
}
public void setHostNames(List<String> hostNames) {
this.hostNames = hostNames;
}
}
Main Method
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Server server = mapper.readValue("{\"host_names\":[\"www.host1.com\",\"www.host2.com\"]}", Server.class);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(server);
System.out.println(json);
}
Output
"www.host1.com,www.host2.com"
This method will only be useful if your bean class has no other fields to serialize.
Related
In Apache Johnzon, is there a way to hava a generic field that contains dynamic JSON data, not mappable to a pre-defined POJO?
In Jackson you can simply use ObjectNode as a generic container, have some JSON processing on it, and then write the whole object in JSON format.
In Jackson it works as expected using ObjectNode, here is my code:
public class JsonTest {
private String myStaticKey = "foo";
private ObjectNode jsonData;
//code to initialize ObjectNode + getters + setters
#JsonIgnore
public void addValue(String key, String value) {
jsonData.put(key, value);
}
#JsonIgnore
public String toJson() {
return new ObjectMapper().writeValueAsString(this);
}
}
public class MainTest {
public static void main(String[] args) {
JsonTest t = new JsonTest();
t.addValue("myDynamicKey", "bar");
System.out.println(t.toJson());
}
}
Expected result:
{
"myStaticKey": "foo",
"jsonData": {
"myDynamicKey": "bar"
}
}
Diferent results occur when mapping an object containing a field starting with "x" to org.json.JSONObject and com.fasterxml.jackson.core.ObjectMapper:
JSONObject
{"one":"One"}
ObjectMapper
{"one":"One","xOne":"xOne"}
Why does the JSONObject not include the "xOne" field?
public class Test {
private String one;
private String xOne;
public String getOne() {
return one;
}
public void setOne(String one) {
this.one = one;
}
public String getxOne() {
return xOne;
}
public void setxOne(String xOne) {
this.xOne = xOne;
}
#Override
public String toString() {
return "Test [one=" + one + ", xOne=" + xOne + "]";
}
}
public class PojoToJson {
public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {
Test test = new Test();
test.setOne("One");
test.setxOne("xOne");
JSONObject json = new JSONObject(test);
System.out.println("JSONObject o/p: " + json);
ObjectMapper mapper = new ObjectMapper();
String mapperString = mapper.writeValueAsString(test);
System.out.println("ObjectMapper o/p: " + mapperString);
}
}
Here is my output difference using JSONObject and ObjectMapper:
According to the Jackson reference documentation:
In absence of a registered custom strategy, the default Java property
naming strategy is used, which leaves field names as is, and removes
set/get/is prefix from methods (as well as lower-cases initial
sequence of capitalized characters).
As I understand it, this means that Jackson will understand that getxOne() actually correspond to xOne property.
org.json.JSONObject may have a different naming strategy (which I was not able to find anywhere) and hence the reason for getxOne() to work with Jackson's ObjectMapper but not with org.json.JSONObject.
I want to keep a part of a JSON as String value.
As far as i know, there is no way with Annotations, but i could not find a way how to get the full Object/Array value as String.
There is a Workaround, which works, by reading it as an Object and instantly write it back as an String by using the ObjectMapper of Jackson.
You can imagine, this is a horrible solution for very big JSONs.
public class DeserializeTest {
private static ObjectMapper mapper;
public static void main(String[] args) throws IOException {
mapper = Jackson2ObjectMapperBuilder.json().build();
mapper.findAndRegisterModules();
SimpleModule module = new SimpleModule();
module.addDeserializer(TestClassWrapper.class, new TestDeserializer());
mapper.registerModule(module);
String json = "{\"name\":\"testprop\", \"data\":[{\"prop\":\"test\"},{\"prop\":\"test1\"},{\"prop\":\"test2\"}]}";
TestClassWrapper t = mapper.readValue(json, TestClassWrapper.class);
// later in program, when i know the expected class
TestClass o = unwrap(t, new TypeReference<ArrayList<Test2>>() {});
}
public static class TestClassWrapper {
String name;
String data;
// removed getter and setter
}
public static class TestClass {
String name;
List<Test2> data;
// removed getter and setter
}
public static class Test2 {
String prop;
// removed getter and setter
}
public static class TestDeserializer extends JsonDeserializer<TestClassWrapper> {
#Override
public TestClassWrapper deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
TestClassWrapper t = new TestClassWrapper();
String key = p.getCurrentName();
if (key == null) {
p.nextToken();
key = p.getCurrentName();
}
for (; key != null; key = p.nextFieldName()) {
p.nextToken();
switch (key) {
case "name":
t.name = p.getValueAsString();
break;
case "data":
// what i tried:
System.out.println(p.getText()); // [
System.out.println(p.getValueAsString()); // NULL
System.out.println(p.getCurrentValue()); //NULL
System.out.println(p.getCurrentToken()); // [ TOKEN
System.out.println(p.getParsingContext().getCurrentValue()); // NULL
System.out.println(p.getParsingContext().toString()); // [0]
System.out.println(p.getEmbeddedObject()); // NULL
System.out.println(p.getTextCharacters()); // [
try {
System.out.println(ctxt.readValue(p, String.class)); // MismatchedInputException
} catch (MismatchedInputException e){}
// The only way i could make it work.
// Parse to a object and write it back as string.
StringBuilder sb = new StringBuilder();
Iterator<Object> it = p.readValuesAs(Object.class);
while (it.hasNext()) {
sb.append(mapper.writeValueAsString(it.next()));
sb.append(it.hasNext() ? "," : "");
}
t.data = p.getCurrentToken() == JsonToken.END_ARRAY ? "[" + sb.toString() + "]" : sb.toString();
break;
}
}
return t;
}
}
public static TestClass unwrap(TestClassWrapper t, TypeReference targetClass) throws IOException {
TestClass o = new TestClass();
o.name = t.name;
o.data = mapper.readValue(t.data, targetClass);
return o;
}
}
How can i tell the JsonParser object, to just give me the String of the current value?
(For data this would be: "[{"prop":"test"}, {"prop":"test1"}, {"prop":"test2"}]")
I have a json a file that doesnt contain only my api i am new to json and trying to get my api parameters from the file
"operators": {
"tez" : {
"api": "www.my-tour.com/search/getResult",
"parameters": [
{
"country": "Canada",
"queryParameters": {
"priceMin": ["0"],
"priceMax":["150000"],
"currency":["5561"],
"nightsMin":[1,2,3,4,5,6,7,8,9,10,11,12,13],
"nightsMax":[1,2,3,4,5,6,7,8,9,10,11,12,13]
In my app operator is just simple the company that owns the api so i have many operators so "tez" is the name of the company and below is its api and param
#Override
public JsonObject fetchData(String url) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DAY_OF_MONTH, 20);
for (int i = 1; i <= 180; i++) {
String formattedDate = dateFormat.format(calendar);
url += "&after=" + formattedDate + "&before=" + formattedDate;
// how can i get the api iteratively to get all api param
JsonObject json = new JsonObject().getJsonObject("tez");
// TODO call eternal API here
JSONParser parser = new JSONParser();
JsonObject a = null;
try {
FileReader fileReader = new FileReader("\\home\\user\\MyProjects\\MicroserviceBoilerPlate\\src\\config\\local_file.json");
a = (JsonObject) parser.parse(fileReader);
} catch (Exception e1) {
e1.printStackTrace();
}
This above is what i am came up with but its not correct im not able to access the json file and how can i iterate through the parameters so i can add them to the api
www.my-tour.com/search/getResult?priceMin=0&priceMax=150000¤cy=+value &nightsMin= + value &nightsMax=+values etc
Note: This is a vertx app and i am using JsonObject and other Json specific api's
You could just make an object of the JSON properties in the file
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.List;
#JsonIgnoreProperties(ignoreUnknown = true)
public class TezModel {
public Operators operators;
public String getApi() {
return operators.tez.api;
}
public List<String> getPriceMin() {
return operators.tez.parameters.get(0).queryParameters.priceMin;
}
public List<String> getPriceMax() {
return operators.tez.parameters.get(0).queryParameters.priceMax;
}
public List<String> getCurrency() {
return operators.tez.parameters.get(0).queryParameters.currency;
}
public List<Integer> getNightsMin() {
return operators.tez.parameters.get(0).queryParameters.nightsMin;
}
public List<Integer> getNightsMax() {
return operators.tez.parameters.get(0).queryParameters.nightsMax;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Operators {
public Tez tez;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Tez {
public String api;
public List<Parameters> parameters;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Parameters {
public String country;
public QueryParameters queryParameters;
}
#JsonIgnoreProperties(ignoreUnknown = true)
public static class QueryParameters {
public List<String> priceMin;
public List<String> priceMax;
public List<String> currency;
public List<Integer> nightsMin;
public List<Integer> nightsMax;
}
}
And then you could add your parameters to a string using jackson databind
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
TezModel tezModel = mapper.readValue(new File("local_file.json"), TezModel.class);
String api = tezModel.getApi()+ "+priceMin="
+ tezModel.getPriceMin().get(0)
+ "&priceMax=" + tezModel.getPriceMax().get(0)
+ "¤cy=+" + tezModel.getCurrency().get(0)
+ "nightsMin=" + tezModel.getNightsMin().get(0)
+ "nightsMax=" + tezModel.getNightsMax().get(0);
System.out.println(api);
}
I am working on an application where i have to generate a json like this:
[
{"title":"Culture","start":"Salary","end":"Work"},
{"title":"Work","start":"Salary","end":"Work"}
]
But my code generates json like this:
{{"name":"Culture"},[{"name":"Salary"},{"name":"Work"}],}
My code:
public class ParseJson {
public static class EntryListContainer {
public List<Entry> children = new ArrayList<Entry>();
public Entry name;
}
public static class Entry {
private String name;
public Entry(String name) {
this.name = name;
}
}
public static void main(String[] args) {
EntryListContainer elc1 = new EntryListContainer();
elc1.name = new Entry("Culture");
elc1.children.add(new Entry("Salary"));
elc1.children.add(new Entry("Work"));
ArrayList<EntryListContainer> al = new ArrayList<EntryListContainer>();
Gson g = new Gson();
al.add(elc1);
StringBuilder sb = new StringBuilder("{");
for (EntryListContainer elc : al) {
sb.append(g.toJson(elc.name));
sb.append(",");
sb.append(g.toJson(elc.children));
sb.append(",");
}
String partialJson = sb.toString();
if (al.size() > 1) {
int c = partialJson.lastIndexOf(",");
partialJson = partialJson.substring(0, c);
}
String finalJson = partialJson + "}";
System.out.println(finalJson);
}
}
Can anyone help me to generate this json in my required format ?? please thanks in advance
Try this
public class Entry {
public String title;
public String start;
public String end;
}
And in another part of your code
private ArrayList<Entry> entries = new ArrayList<>();
// Fill the entries...
String the_json = new Gson().toJson(entries);
1) First Create your POJO
public class MyJSONObject {
private String title;
private String start;
private String end;
//getter and setter methods
[...]
#Override
public String toString() {
}
}
2) Use com.google.code.gson library
public static void main(String[] args) {
{
ArrayList<MyJSONObject> myJSONArray = new ArrayList<>();
MyJSONObject obj = new MyJSONObject();
obj.setTitle="Culture";
obj.set[...]
myJSONArray.add(obj);
Gson gson = new Gson();
// convert java object to JSON format,
// and returned as JSON formatted string
String json = gson.toJson(myJSONArray);
System.out.println(json);
}
Output : [{"title":"Culture","start":"Salary","end":"Work"}, ...]
I recommend you to use some JSON Java API, like Gson. It's very simple to generate a string json from a POJO object or to create a POJO object from a string json.
The code for generating a string json from a POJO object is like this:
Gson gson = new Gson();
String stringJson = gson.toJson(somePojoObject);
The code for creating a POJO object from a string json is like this:
Gson gson = new Gson();
SomePojoClass object = gson.fromJson(stringJson, SomePojoClass.class);
Note that you can not serialize objects with circular references. This causes infinite recursion.