If I use a YAMLFactory instead of default one (JSON) for ObjectMapper and configure a custom indentation, the indentation is not taken into account
If I don't use YAML output, it works for the JSON output.
Any idea ?
DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF);
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentObjectsWith(indenter);
printer.indentArraysWith(indenter);
ObjectMapper objectMapper = new ObjectMapper( new YAMLFactory() );
objectMapper.setDefaultPrettyPrinter(printer);
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
String string = objectMapper.writeValueAsString(myObject);
Related
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);
I am using Jackson v2.8.2 to serialise JSON to a file.
I have created a custom serializer and implemented the serialize method to customise the JSON output as required.
I am invoking the serializer as follows:
// myClass is the object I want to serialize
SimpleModule module = new SimpleModule();
module.addSerializer(MyClass.class, new MySerializer());
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
mapper.registerModule(module);
try
{
mapper.writeValue(new File("json.txt"), myClass);
}
catch (JsonProcessingException e)
{
...
}
The JSON file is created and the content looks good.
The file is formatted according to the DefaultPrettyPrinter but I want to use my own custom PrettyPrinter, which I have already implemented.
How do I do that?
I've tried the following:
MyPrettyPrinter myPrettyPrinter = new MyPrettyPrinter();
mapper.writer(myPrettyPrinter);
mapper.writeValue(new File("json.txt"), myClass);
but that isn't invoking my custom printer.
Sometimes, depending on what you want to achieve, you could use the DefaultPrettyPrinter and just customize the Indenter, as following:
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
Indenter indenter = new CustomSpaceIndenter();
printer.indentObjectsWith(indenter); // Indent JSON objects
printer.indentArraysWith(indenter); // Indent JSON arrays
There's a related question about it: Serialize JsonNode to a very specific JSON format in Jackson
The reason for this is that the invocation of writer returns a new instance of the ObjectWriter. In fact, ObjectMapper has a lot of factory methods that construct new objects for you to work with.
The sourcecode from ObjectMapper:
/**
* Factory method for constructing {#link ObjectWriter} that will
* serialize objects using specified pretty printer for indentation
* (or if null, no pretty printer)
*/
public ObjectWriter writer(PrettyPrinter pp) {
if (pp == null) { // need to use a marker to indicate explicit disabling of pp
pp = ObjectWriter.NULL_PRETTY_PRINTER;
}
return _newWriter(getSerializationConfig(), /*root type*/ null, pp);
}
So for you that means, that you should change your code to:
MyPrettyPrinter myPrettyPrinter = new MyPrettyPrinter();
ObjectWriter myWriter = mapper.writer(myPrettyPrinter);
myWriter.writeValue(new File("json.txt"), myClass);
Note the assignment to myWriter so that you are using the correct writer when calling writeValue
Here is an example using the ObjectMapper and the default pretty printer:
public class OMTest {
public static void main(String[] args) throws IOException {
// test string
String json = " {\"a\" : \"b\", \"c\" : \"d\" } ";
// mapper
ObjectMapper mapper = new ObjectMapper();
// json tree
JsonNode tree = mapper.readTree(json);
// the objectWriter assigned with a pretty printer
ObjectWriter myWriter = mapper.writer(new DefaultPrettyPrinter());
// print without pretty printer (using mapper)
System.out.println(mapper.writeValueAsString(tree));
System.out.println();
// print with writer (using the pretty printer)
System.out.println(myWriter.writeValueAsString(tree));
}
}
This prints:
{"a":"b","c":"d"}
{
"a" : "b",
"c" : "d"
}
Where the first line uses the mapper, while the second print uses the writer.
Cheers,
Artur
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());
I am generating jsonschema from java using the jackson classes:
ObjectMapper mapper = new ObjectMapper();
JsonSchema jsonSchema = mapper.generateJsonSchema(Sample.class);
ObjectNode node = jsonSchema.getSchemaNode();
ObjectWriter or = mapper.defaultPrettyPrintingWriter();
or.writeValue(System.out, node);
This works fine, but I was wondering how I might get descriptions added, e.g. from the type javadoc.
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);