How to use indentation in gson to generate a json file - java

I have to generate a json file containing indentation. I was using Jackson for this but it adds a space before the colon and I don't need it, so I decided to use Gson.
After changing the code, I figured out that by default Gson don't use indentation but Jackson does. Does anyone know if it is possible in Gson to get indentation and how to do it?
For generating the json file with Gson I made this:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder = gsonBuilder.setPrettyPrinting();
Gson gson = gsonBuilder.create();
Writer writer = new FileWriter(propsFile);
gson.toJson(properties, writer);

You can only employ the default indentation provided by setPrettyPrinting() and you cannot change its size or indentation characters. Please refer to the official information about it: Compact Vs. Pretty Printing for JSON Output Format.

Possible duplicate of https://stackoverflow.com/a/41509714/4379906
Use Jackson and and configure it not to add spaces before colon:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
</dependency>
CustomPrettyPrinter.java:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import java.io.IOException;
class CustomPrettyPrinter extends DefaultPrettyPrinter {
public CustomPrettyPrinter() {
super();
}
public CustomPrettyPrinter(DefaultPrettyPrinter base) {
super(base);
}
#Override
public void writeObjectFieldValueSeparator(JsonGenerator g) throws IOException {
g.writeRaw(": ");
}
#Override
public DefaultPrettyPrinter createInstance() {
return new CustomPrettyPrinter(this);
}
}
UseJackson.java:
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
public class UseJackson {
public static void main(String[] args) throws IOException {
DefaultPrettyPrinter.Indenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF);
DefaultPrettyPrinter printer = new CustomPrettyPrinter();
printer.indentArraysWith(indenter);
printer.indentObjectsWith(indenter);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDefaultPrettyPrinter(printer);
Properties properties = new Properties();
properties.put("foo", "3");
properties.put("bar", "4");
objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File("a.json"), properties);
}
}
Use Gson and configure indentation:
UseGson.java:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class UseGson {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.put("foo", "3");
properties.put("bar", "4");
JsonWriter jsonWriter = new JsonWriter(new FileWriter("a.json"));
jsonWriter.setIndent(" ");
Gson gson = new GsonBuilder().serializeNulls().create();
gson.toJson(properties, Properties.class, jsonWriter);
jsonWriter.close();
}
}

Related

How to show on the web json

I'm using java spring boot i can print json result on the terminal but i want to show on the web so how can i change this code it to show on web
package com.tutorial.springboot;
import com.google.gson.Gson;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import lombok.var;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.sql.Driver;
public class Application {
public static void main(String[] args) throws IOException, ClassNotFoundException{
var prop = new Properties();
prop.load(new FileInputStream("src/main/resources/Application.properties"));
var ds = new SimpleDriverDataSource();
ds.setDriverClass(((Class<Driver>) Class.forName(prop.getProperty("jdbc.driver"))));
ds.setUrl(prop.getProperty("jdbc.url"));
ds.setUsername(prop.getProperty("jdbc.username"));
ds.setPassword(prop.getProperty("jdbc.password"));
var sql = "SELECT * FROM ked_evaluation_data";
var jtm = new JdbcTemplate(ds);
List<Map<String, Object>> rows = (List<Map<String, Object>>) jtm.queryForList(sql);
Gson gson = new Gson();
String jcart=gson.toJson(rows);
System.out.println(jcart);
//rows.forEach(System.out::println);
}
}
In summary, i want to know how to change the code to show the result on web
If someone knows that please teach me!! thank you!
You need to use Spring boot rest controller here like below
#RestController
public class HelloController {
#RequestMapping("/json")
public String index() {
var prop = new Properties();
prop.load(new FileInputStream("src/main/resources/Application.properties"));
var ds = new SimpleDriverDataSource();
ds.setDriverClass(((Class<Driver>) Class.forName(prop.getProperty("jdbc.driver"))));
ds.setUrl(prop.getProperty("jdbc.url"));
ds.setUsername(prop.getProperty("jdbc.username"));
ds.setPassword(prop.getProperty("jdbc.password"));
var sql = "SELECT * FROM ked_evaluation_data";
var jtm = new JdbcTemplate(ds);
List<Map<String, Object>> rows = (List<Map<String, Object>>) jtm.queryForList(sql);
Gson gson = new Gson();
String jcart=gson.toJson(rows);
return jcart;
}
}
Application.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Call it from the web using url like http://localhost:8080/json
(Replace host and port, also to use rest controller you may need to add dependencies if not already present)
Hope this helps

Create Json string from Map<Object,Object> [duplicate]

I want to serialize a Map with Jackson.
The Date should be serialized as a timestamp, like all my other dates.
The following code renders the keys in the form "Tue Mar 11 00:00:00 CET 1952" (which is Date.toString()) instead of the timestamp.
Map<Date, String> myMap = new HashMap<Date, String>();
...
ObjectMapper.writeValue(myMap)
I assume this is because of type erasure and jackson doesn't know at runtime that the key is a Date. But I didn't find a way to pass a TypeReference to any writeValue method.
Is there a simple way to achieve my desired behaviour or are all keys always rendered as Strings by jackson?
Thanks for any hint.
The default map key serializer is StdKeySerializer, and it simply does this.
String keyStr = (value.getClass() == String.class) ? ((String) value) : value.toString();
jgen.writeFieldName(keyStr);
You could make use of the SimpleModule feature, and specify a custom key serializer, using the addKeySerializer method.
And here's how that could be done.
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.map.type.MapType;
import org.codehaus.jackson.map.type.TypeFactory;
public class CustomKeySerializerDemo
{
public static void main(String[] args) throws Exception
{
Map<Date, String> myMap = new HashMap<Date, String>();
myMap.put(new Date(), "now");
Thread.sleep(100);
myMap.put(new Date(), "later");
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(myMap));
// {"Mon Jul 04 11:38:36 MST 2011":"now","Mon Jul 04 11:38:36 MST 2011":"later"}
SimpleModule module =
new SimpleModule("MyMapKeySerializerModule",
new Version(1, 0, 0, null));
module.addKeySerializer(Date.class, new DateAsTimestampSerializer());
MapType myMapType = TypeFactory.defaultInstance().constructMapType(HashMap.class, Date.class, String.class);
ObjectWriter writer = new ObjectMapper().withModule(module).typedWriter(myMapType);
System.out.println(writer.writeValueAsString(myMap));
// {"1309806289240":"later","1309806289140":"now"}
}
}
class DateAsTimestampSerializer extends JsonSerializer<Date>
{
#Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException
{
jgen.writeFieldName(String.valueOf(value.getTime()));
}
}
Update for the latest Jackson (2.0.4):
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.TypeFactory;
public class CustomKeySerializerDemo
{
public static void main(String[] args) throws Exception
{
Map<Date, String> myMap = new HashMap<Date, String>();
myMap.put(new Date(), "now");
Thread.sleep(100);
myMap.put(new Date(), "later");
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(myMap));
// {"2012-07-13T21:14:09.499+0000":"now","2012-07-13T21:14:09.599+0000":"later"}
SimpleModule module = new SimpleModule();
module.addKeySerializer(Date.class, new DateAsTimestampSerializer());
MapType myMapType = TypeFactory.defaultInstance().constructMapType(HashMap.class, Date.class, String.class);
ObjectWriter writer = new ObjectMapper().registerModule(module).writerWithType(myMapType);
System.out.println(writer.writeValueAsString(myMap));
// {"1342214049499":"now","1342214049599":"later"}
}
}
class DateAsTimestampSerializer extends JsonSerializer<Date>
{
#Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException
{
jgen.writeFieldName(String.valueOf(value.getTime()));
}
}
As usual, Bruce's answer is right on the spot.
One additional thought is that since there is a global setting for serializing Date values as timestamps:
SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS
Maybe that should apply here as well. And/or at least use standard ISO-8601 format for text. The main practical issue there is that of backwards compatibility; however, I doubt that current use of plain toString() is very useful as it is neither efficient nor convenient (to read back the value).
So if you want, you might want to file a feature request; this sounds like sub-optimal handling of Map keys by Jackson.
Since Jackson 2.0 (maybe 1.9, too), WRITE_DATE_KEYS_AS_TIMESTAMPS can be used to change this particular behavior.
Usage example for ObjectMapper:
ObjectMapper m = new ObjectMapper().configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, true);
and for ObjectWriter:
ObjectWriter w = mapper.with(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);

marshal Object to CSV

I'm trying to marshal an Object into a csv String. I have created a method that can convert any object into a csv String but I keep getting the exception:
java.lang.NoSuchMethodError: org.codehaus.jackson.map.ObjectMapper.writer(Lorg/codehaus/jackson/FormatSchema;)Lorg/codehaus/jackson/map/ObjectWriter;
Marshal method:
public static final synchronized String marshal(final Object object, final CsvSchema csvSchema) throws IOException {
String CSV_FILTER_NAME = "csvFilter";
HashSet<String> columnNames = new HashSet<>();
for (CsvSchema.Column column : csvSchema) {
columnNames.add(column.getName());
}
SimpleBeanPropertyFilter csvReponseFilter = new SimpleBeanPropertyFilter.FilterExceptFilter(columnNames);
FilterProvider filterProvider = new SimpleFilterProvider().addFilter(CSV_FILTER_NAME, csvReponseFilter);
CsvMapper csvMapper = new CsvMapper();
csvMapper.setFilters(filterProvider);
csvMapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
#Override
public Object findFilterId(AnnotatedClass annotatedClass) {
return CSV_FILTER_NAME;
}
});
ObjectWriter objectWriter = csvMapper.writer(csvSchema);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
objectWriter.writeValue(byteArrayOutputStream, csvSchema);
return new String(byteArrayOutputStream.toByteArray(), "UTF-8");
}
Main method:
public static void main(String args[]) {
CsvSchema csvSchema = CsvSchema.builder()
.addColumn("name")
.addColumn("age")
.addColumn("height")
.addColumn("weight")
.setUseHeader(true)
.build()
.withLineSeparator("\n");
Person person = new Person("Tim", "32", "184", "100");
try {
System.out.println(CsvUtilities.marshal(person, csvSchema));
} catch (IOException ex) {
Logger.getLogger(CsvUtilities.class.getName()).log(Level.SEVERE, null, ex);
}
}
What is causing this exception?
EDIT Here's all my imports:
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.List;
import java.util.logging.Logger;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.map.introspect.AnnotatedClass;
import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
import org.codehaus.jackson.map.ser.FilterProvider;
import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;
import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;
See the jars in your class path. It could be that there are two or different version of jackson jar which does not have this method. Maybe an older version been laoded in by the Class loader.
Also inspect your dependencies which you have added to the project.

Java: CSV to XML using Jackson

I'm trying to update the following code to output a CSV file into XML. The code below does a brilliant job in converting the CSV to JSON using the headers in the CSV to make the required JSON.
But I want to output as XML instead, and I can't seem to find any good advice to complete this.
Would appreciate some pointers.
package reader;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
public class JacksonPackage
{
public static void main(String[] args) throws Exception
{
File input = new File("c:\\temp\\data.csv");
File output = new File("c:\\temp\\data.json");
List<Map<?, ?>> data = readObjectsFromCsv(input);
writeAsJson(data, output);
}
public static List<Map<?, ?>> readObjectsFromCsv(File file)
throws IOException
{
CsvSchema bootstrap = CsvSchema.emptySchema().withHeader();
CsvMapper csvMapper = new CsvMapper();
MappingIterator<Map<?, ?>> mappingIterator = csvMapper
.reader(Map.class).with(bootstrap).readValues(file);
return mappingIterator.readAll();
}
public static void writeAsJson(List<Map<?, ?>> data, File file)
throws IOException
{
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(file, data);
}
}
Isn't it just a matter of replacing ObjectMapper with XmlMapper?

Dealing with randomly generated and inconsistent JSON field/key names using GSON

I have the following JSON snippets:
{ "randomlygeneratedKeyname0" : "some-value",
"randomlygeneratedKeyname1": {
"randomlygeneratedKeyname2" : {
"randomlygeneratedKeyname3": "some-value",
"randomlygeneratedKeyname4": "some-value"
},
"randomlygeneratedKeyname5": {
"randomlygeneratedKeyname6": "some-value",
"randomlygeneratedKeyname7": "some-value"
}
}
}
Notes that I don't know the name of randomlygeneratedKeyname and their naming convention is inconsistent so I could not create my corresponding Java field/variable names.
How do I (de)serialize it in GSON?
Thanks in advance for your help.
I'm pleased to report that with GSON 2.0 supports default maps and lists without effort. Deserialize like this:
Object o = new Gson().fromJson(json, Object.class);
The result will be a Map with String keys and either String or Map values.
Serialize that map back to JSON like this:
String json = new Gson().toJson(o);
We hope to release GSON 2.0 in October 2012. You can get it early from GSON SVN.
Code dump solution:
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
public class Foo
{
public static void main(String[] args) throws Exception
{
Type mapStringObjectType = new TypeToken<Map<String, Object>>() {}.getType();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(mapStringObjectType, new RandomMapKeysAdapter());
Gson gson = gsonBuilder.create();
Map<String, Object> map = gson.fromJson(new FileReader("input.json"), mapStringObjectType);
System.out.println(map);
}
}
class RandomMapKeysAdapter implements JsonDeserializer<Map<String, Object>>
{
#Override
public Map<String, Object> deserialize(JsonElement json, Type unused, JsonDeserializationContext context)
throws JsonParseException
{
// if not handling primitives, nulls and arrays, then just
if (!json.isJsonObject()) throw new JsonParseException("some meaningful message");
Map<String, Object> result = new HashMap<String, Object> ();
JsonObject jsonObject = json.getAsJsonObject();
for (Entry<String, JsonElement> entry : jsonObject.entrySet())
{
String key = entry.getKey();
JsonElement element = entry.getValue();
if (element.isJsonPrimitive())
{
result.put(key, element.getAsString());
}
else if (element.isJsonObject())
{
result.put(key, context.deserialize(element, unused));
}
// if not handling nulls and arrays
else
{
throw new JsonParseException("some meaningful message");
}
}
return result;
}
}

Categories

Resources