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);
Related
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?
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));
This is probably a quick answer to a very novice question. I am having trouble wrapping my head around how to get JSON text dbpedia extraction server running from a localhost. The server is running fine, I followed the official instructions.
I have read the other StackOverflow questions about parsing JSON in java and what I am having trouble understanding is how to parse the JSON when the schema or structure is unknown.
For example in my code I try to grab the JSON from localhost and put it into a java object. But all the examples of parsing JSON online use a predesigned java object and all the JSON keys are mapped to an object's fields. (ie Employee class: name,job,email,id,phone)
String sURL = "http://localhost:9999/server/extraction/en/extract?title=" + wikipage + "&revid=&format=rdf-json&extractors=custom"; //just a string
URL url = new URL(sURL);
Reader pageReader = new InputStreamReader(url.openConnection().getInputStream());
Gson g = new Gson();
JsonReader jr = new JsonReader(new InputStreamReader((InputStream) request.getContent()));
jr.setLenient(true);
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //convert the input stream to a json element
JsonObject rootobj = root.getAsJsonObject(); //may be an array, may be an object.
I now have this "json object" for the film "Blue Velvet" I can parse/iterate with jr.hasNext() or rootobj.getAsJsonArray().
Am I going about this correctly?
I feel like I am reinventing the wheel. Is there a standard way of parsing DBpedia JSON objects in Java?
At least the Jackson JSON library allows you to parse incoming JSON into a Map. If the keys and values of the JSON can be of any type, then you need to use Map<Object, Object>, which is a bit cumbersome, but anyways this should work:
ObjectMapper mapper = new ObjectMapper();
Map<Object, Object> parsedJSON = mapper.readValue(incomingJSON,
mapper.getTypeFactory().constructMapType(
LinkedHashMap.class,
Object.class,
Object.class));
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());
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);