Insert org.json.JSONArray into jackson ObjectNode - java

I have got stuck trying to insert a JSONArray into a Jackson ObjectNode. This is what I am trying to do:
public void myMethod(JSONArray jsonArray) {
ObjectNode payload = objectMapper.createObjectNode(0);
payload.put("array", /* jsonArray */);
payload.put(/* some other things */);
...
}
It feels like something really silly but what is actually the best way to do it?!
EDIT: I am sorry beacause I did not mention an important point, that is I have to serialize the ObjectNode once I finished building it, so using putPOJO() is not a possibility.

I like aribeiro's approach more. You can use the putPOJO() method to do this. For example:
// Incoming org.json.JSONArray.
JSONArray incomingArray = new JSONArray("[\"Value1\",\"Value2\"]");
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode payload = objectMapper.createObjectNode();
// Adds the JSONArray node to the payload as POJO (plain old Java object).
payload.putPOJO("array", incomingArray);
System.out.println(objectMapper.writeValueAsString(payload));
Javadoc can be found here.
Note: here's a previous implementation that I submitted using readTree():
// Incoming org.json.JSONArray.
JSONArray incomingArray = new JSONArray("[\"Value1\",\"Value2\"]");
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode payload = objectMapper.createObjectNode();
// Reads the JSON array into a Jackson JsonNode.
JsonNode jsonNode = objectMapper.readTree(incomingArray.toString());
// Sets the Jackson node on the payload.
payload.set("array", jsonNode);
System.out.println(objectMapper.writeValueAsString(payload));

Related

How to pass JSON from static file to rest controller SpringBoot App

I have a stable SpringBoot project that runs. I want to add a end point that reads a json file from classpath and passes it through to the response without having to create any Model objects (pass thru).
I have no issues reading the json file into JsonNode or ObjectNode, I'm struggling with where to go next to set the data in my response object.
Added this caveat later, I do need to update the json from a database.
Ok, paired up with a colleague at work and we tried two things, return a string (escapes strings in REST output - returns a big String.) not good. What worked is setting the response object to a and calling mapper.readValue(jsonFeed, Map.class), that returned the JSON in proper object notation.
#Value("${metadata.json.file}") //defined in application.context
private Resource metaJsonFileName;
public String getJsonFromFile(List<UnitUiItem> uiitems){
JsonNode root;
ObjectMapper mapper = new ObjectMapper();
InputStream stream = metaJsonFileName.getInputStream();
root = mapper.readTree(stream);
JsonNode dataNode = root.get("data");
JsonNode optionDataNode = dataNode.get("storelocation");
((ObjectNode)optionDataNode).putArray("units");
for(UnitUiItem item : uiitems){
JsonNode unitNode = ((ObjectNode)optionDataNode).withArray("units").addObject();
((ObjectNode)unitNode).put("code",item.getCode());
((ObjectNode)unitNode).put("displayName",item.getDisplayName());
}
LOGGER.info("buildMetaJson exit");
return root.toString();
}
//calling method
String jsonFeed = getJsonFromFile();
ObjectMapper mapper = new ObjectMapper();
response.setData(mapper.readValue(jsonFeed, Map.class));
I have some code cleanup to do.. any cleaner ways of doing this?

PrettyPrint JSON with Jackson

I am using jackson 2.8.4 and try to pretty-print (i.e. format nicely with indentation) some JSON that I have got in a one-line String called json.
I tried
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json);
and
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
json = mapper.writeValueAsString(json);
but the JSON String json still is just one line.
EDIT:
Before:
{"artifacts":[{"general":{"name":"jersey-client-2.26.jar","path":"doartifac/spielwiese-group-cache/org/glassfish/jersey/core/jersey-client/2.26/jersey-client-2.26.jar","pkg_type":"Maven","sha256":"3e44b7db8691eb0b2a6751eda888150b9ba1092a5805f11e4727fd4904407a41","component_id":"org.glassfish.jersey.core:jersey-client:2.26"},"issues":[],"licenses":[{"name":"CDDL-1.0","full_name":"Common Development and Distribution License (CDDL)\n 1.0","more_info_url":["http://www.opensource.org/licenses/cddl1.php","https://spdx.org/licenses/CDDL-1.0","https://spdx.org/licenses/CDDL-1.0.html","http://www.opensource.org/licenses/cddl1"],"components":["gav://org.glassfish.jersey.core:jersey-client:2.26"]},{"name":"GPL-2.0","full_name":"The GNU General Public License Version 2","more_info_url":["http://www.opensource.org/licenses/GPL-2.0","http://www.opensource.org/licenses/gpl-2.0.php","https://spdx.org/licenses/GPL-2.0","https://spdx.org/licenses/GPL-2.0.html","http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html"],"components":["gav://org.glassfish.jersey.core:jersey-client:2.26"]}]}]}
After:
"{\"artifacts\":[{\"general\":{\"name\":\"jersey-client-2.26.jar\",\"path\":\"doartifac/spielwiese-group-cache/org/glassfish/jersey/core/jersey-client/2.26/jersey-client-2.26.jar\",\"pkg_type\":\"Maven\",\"sha256\":\"3e44b7db8691eb0b2a6751eda888150b9ba1092a5805f11e4727fd4904407a41\",\"component_id\":\"org.glassfish.jersey.core:jersey-client:2.26\"},\"issues\":[],\"licenses\":[{\"name\":\"CDDL-1.0\",\"full_name\":\"Common Development and Distribution License (CDDL)\\n 1.0\",\"more_info_url\":[\"http://www.opensource.org/licenses/cddl1.php\",\"https://spdx.org/licenses/CDDL-1.0\",\"https://spdx.org/licenses/CDDL-1.0.html\",\"http://www.opensource.org/licenses/cddl1\"],\"components\":[\"gav://org.glassfish.jersey.core:jersey-client:2.26\"]},{\"name\":\"GPL-2.0\",\"full_name\":\"The GNU General Public License Version 2\",\"more_info_url\":[\"http://www.opensource.org/licenses/GPL-2.0\",\"http://www.opensource.org/licenses/gpl-2.0.php\",\"https://spdx.org/licenses/GPL-2.0\",\"https://spdx.org/licenses/GPL-2.0.html\",\"http://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html\"],\"components\":[\"gav://org.glassfish.jersey.core:jersey-client:2.26\"]}]}]}"
try to check this one: Convert JSON String to Pretty Print JSON output using Jackson
You need first read existing JSON to Object, then serialize it.
Because now you are just serializing string.
UPD: You need to doo something like this:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
String json = "here your ugly json";
Object jsonObject = mapper.readValue(json, Object.class);
String prettyFormatted = mapper.writeValueAsString(jsonObject);

Jackson build JSON from values, term?

The documentation in Jackson is horrible and it only states how it is possible to create JSON from objects and streams, not piece by piece. I cannot find the term to be able to search for more examples/documentation.
I would like to do something like the following.
JsonObject jsonObject = new JsonObject().add("type", "unregister").add("id",id);
return jsonObject.toString();
Which would return {"type":"unregister","id":2} as an example. Can anyone nudge me in the right direction?
The corresponding JsonObject in Jackson is ObjectNode. You can use its various xyzNode(...) factory methods to produce JsonNode subtype instances. You can then use ObjectNode#set(String, JsonNode) to add them.
JsonNodeFactory nc = new JsonNodeFactory(false); // or true, depending
ObjectNode root = new ObjectNode(nc);
TextNode text = root.textNode("unregister");
NumericNode id = root.numberNode(2);
root.set("type", text);
root.set("id", id);
Then
System.out.println(node);
produces
{"type":"unregister","id":2}
You can also create an ObjectNode through the ObjectMapper which uses the ObjectMapper's JsonNodeFactory.
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = mapper.createObjectNode();
Jackson maps Java Objects to JSON, so their documentation is telling you what it does (it does not provide a sort of builder API to arbitrarily compose JSON documents)
If you want to map arbitrary key/values, use a Map<String, Object> and use Jackson to turn it into JSON. You can mix heterogeneous map values and get the result you want this way, pseudo:
Map<String, Object> map = new HashMap<>();
map.put("type", "unregister");
map.put("id", id);
StringWriter sw = new StringWriter();
mapper.writeValue(sw, map); // mapper is a ObjectMapper instance
System.out.println(sw.toString());

how to parse a JSON string into ObjectNode in Jackson?

First of all could anyone explain to me What are differences between ObjectNode and JsonNode, and where they used?
Then if I want to convert a JSON string into ObjectNode what can I do?
You can do:
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.valueToTree("{\"k1\":\"v1\"}")
JsonNode it is a super class of ObjectNode.
You can find the differences in the API.

How to parse a JSON string into JsonNode in Jackson?

It should be so simple, but I just cannot find it after being trying for an hour.
I need to get a JSON string, for example, {"k1":v1,"k2":v2}, parsed as a JsonNode.
JsonFactory factory = new JsonFactory();
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = jp.readValueAsTree();
gives
java.lang.IllegalStateException: No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree
A slight variation on Richards answer but readTree can take a string so you can simplify it to:
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");
You need to use an ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = mapper.getJsonFactory(); // since 2.1 use mapper.getFactory() instead
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = mapper.readTree(jp);
Further documentation about creating parsers can be found here.
A third variant:
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);
Richard's answer is correct. Alternatively you can also create a MappingJsonFactory (in org.codehaus.jackson.map) which knows where to find ObjectMapper. The error you got was because the regular JsonFactory (from core package) has no dependency to ObjectMapper (which is in the mapper package).
But usually you just use ObjectMapper and do not worry about JsonParser or other low level components -- they will just be needed if you want to data-bind parts of stream, or do low-level handling.
import com.github.fge.jackson.JsonLoader;
JsonLoader.fromString("{\"k1\":\"v1\"}")
== JsonNode = {"k1":"v1"}
New approach to old question.
A solution that works from java 9+
ObjectNode agencyNode = new ObjectMapper().valueToTree(Map.of("key", "value"));
is more readable and maintainable for complex objects. Ej
Map<String, Object> agencyMap = Map.of(
"name", "Agencia Prueba",
"phone1", "1198788373",
"address", "Larrea 45 e/ calligaris y paris",
"number", 267,
"enable", true,
"location", Map.of("id", 54),
"responsible", Set.of(Map.of("id", 405)),
"sellers", List.of(Map.of("id", 605))
);
ObjectNode agencyNode = new ObjectMapper().valueToTree(agencyMap);

Categories

Resources