Jackson CSV's WRAP_AS_ARRAY - java

According to http://fasterxml.github.io/jackson-dataformat-csv/javadoc/2.0.0/com/fasterxml/jackson/dataformat/csv/CsvParser.Feature.html, WRAP_AS_ARRAY is:
Feature that determines how stream of records (usually CSV lines, but sometimes multiple lines when linefeeds are included in quoted values) is exposed: either as a sequence of Objects (false), or as an array of Objects (true).
What is the difference between a "sequence of Objects" and an "array of Objects"? The description seems the same to me.

Parsing to a sequence of objects: you call readValues() and get a MappingIterator, which gives you the objects one-by-one. Equivalent to input containing multiple JSON objects, one after the other.
Parsing to an array of objects: you call readValue() and get a List of the objects. Equivalent to input containing a JSON array.
Examples:
#Test
public void parses_csv_to_object_list() throws Exception {
String csv = "id,name\n1,Red\n2,Green\n3,Blue";
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(ColourData.class).withHeader();
ObjectReader reader = mapper.readerFor(ColourData.class).with(schema);
try (MappingIterator<ColourData> iter = reader.readValues(csv)) {
assertThat(iter.readAll(),
contains(new ColourData(1, "Red"), new ColourData(2, "Green"), new ColourData(3, "Blue")));
}
}
#Test
public void parses_csv_to_object_list_in_one_read() throws Exception {
String csv = "id,name\n1,Red\n2,Green\n3,Blue";
CsvMapper mapper = new CsvMapper().enable(CsvParser.Feature.WRAP_AS_ARRAY);
CsvSchema schema = mapper.schemaFor(ColourData.class).withHeader();
ObjectReader reader = mapper.readerFor(new TypeReference<List<ColourData>>() {
}).with(schema);
assertThat(reader.readValue(csv),
contains(new ColourData(1, "Red"), new ColourData(2, "Green"), new ColourData(3, "Blue")));
}

Related

get a key value pair from a String json (simple object)

Im trying to get a key:value pair from a simple jsonString to add it after into a memory tab. If facing an issue cause my input is a string. and it looks like my loop isnot able to read the key value pair.
I read many topics about it, and im still in trouble with it. As you can see below
{"nom":"BRUN","prenom":"Albert","date_naiss":"10-10-1960","adr_email":"abrun#gmail.com","titre":"Mr","sexe":"F"}
and my method, find only on object... the result is the same in my loop
public static ArrayHandler jsonSimpleObjectToTab(String data) throws ParseException {
if( data instanceof String) {
final var jsonParser = new JSONParser();
final var object = jsonParser.parse(data);
final var array = new JSONArray();
array.put(object);
final var handler = new ArrayHandler("BW_funct_Struct");
for( KeyValuePair element : array) {
handler.addCell(element);
Log.warn(handler);
}
return handler;
} else {
throw new IllegalArgumentException("jsonSimpleObjectToTab: do not support complex object" + data + "to Tab");
}
}
i also tryed before to type my array as a List, Object etc, without the keyValuePair object, i would appreciate some help.
Thanks again dear StackOverFlowers ;)
You can try this :
const json = '{"nom":"BRUN","prenom":"Albert","date_naiss":"10-10-1960","adr_email":"abrun#gmail.com","titre":"Mr","sexe":"F"}';
map = new Map();
const obj = JSON.parse(json,(key,value) => {
map.set(key,value)
});
and you'll have every pair stored in map
Simply split the whole line at the commas and then split the resulting parts at the colon. This should give you the individual parts for your names and values.
Try:
supposing
String input = "\"nom\":\"BRUN\",\"prenom\":\"Albert\"";
then
String[] nameValuePairs = input.split(",");
for(String pair : nameValuePairs)
{
String[] nameValue = pair.split(":");
String name = nameValue[0]; // use it as you need it ...
String value = nameValue[1]; // use it as you need it ...
}
You can use TypeReference to convert to Map<String,String> so that you have key value pair.
String json = "{\"nom\":\"BRUN\",\"prenom\":\"Albert\",\"date_naiss\":\"10-10-1960\",\"adr_email\":\"abrun#gmail.com\",\"titre\":\"Mr\",\"sexe\":\"F\"}";
ObjectMapper objectMapper = new ObjectMapper();
TypeReference<Map<String,String>> typeReference = new TypeReference<Map<String, String>>() {
};
Map<String,String> map = objectMapper.readValue(json, typeReference);
I just answered a very similar question. The gist of it is that you need to parse your Json String into some Object. In your case you can parse it to Map. Here is the link to the question with my answer. But here is a short version: you can use any Json library but the recommended ones would be Jackson Json (also known as faster XML) or Gson(by Google) Here is their user guide site. To parse your Json text to a class instance you can use ObjectMapper class which is part of Jackson-Json library. For example
public <T> T readValue(String content,
TypeReference valueTypeRef)
throws IOException,
JsonParseException,
JsonMappingException
See Javadoc. But also I may suggest a very simple JsonUtils class which is a thin wrapper over ObjectMapper class. Your code could be as simple as this:
Map<String, Object> map;
try {
map = JsonUtils.readObjectFromJsonString(input , Map.class);
} catch(IOException ioe) {
....
}
Here is a Javadoc for JsonUtils class. This class is a part of MgntUtils open source library written and maintained by me. You can get it as Maven artifacts or from the Github

Jackson - Using custom PrettyPrinter with custom JsonSerializer

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

Supercsv - unable to find method exception

I have the below implementation.
csvReader = new CsvBeanReader(new InputStreamReader(stream), CsvPreference.STANDARD_PREFERENCE);
lastReadIdentity = (T) csvReader.read(Packages.class, Packages.COLS);
In my Packages.class
I have set my unitcount variable.
public String getUnitCount() {
return unitCount;
}
public void setUnitCount(String unitCount) {
this.unitCount = unitCount;
}
This works fine when it is taken as a string, but when taken as a integer, it throws the below exception. Please help
private int unitCount;
public int getUnitCount() {
return unitCount;
}
public void setUnitCount(int unitCount) {
this.unitCount = unitCount;
}
Exception:
org.supercsv.exception.SuperCsvReflectionException: unable to find method setUnitCount(java.lang.String) in class com.directv.sms.data.SubscriberPackages - check that the corresponding nameMapping element matches the field name in the bean, and the cell processor returns a type compatible with the field
context=null
at org.supercsv.util.ReflectionUtils.findSetter(ReflectionUtils.java:139)
at org.supercsv.util.MethodCache.getSetMethod(MethodCache.java:95)
I'm not sure about SuperCsv, but univocity-parsers should be able to handle this without a hitch, not to mention it is at least 3 times faster to parse your input.
Just annotate your class:
public class SubscriberPackages {
#Parsed(defaultNullRead = "0") // if the file contains nulls, then they will be converted to 0.
private int unitCount; // The attribute name will be matched against the column header in the file automatically.
}
To parse the CSV into beans:
// BeanListProcessor converts each parsed row to an instance of a given class, then stores each instance into a list.
BeanListProcessor<SubscriberPackages> rowProcessor = new BeanListProcessor<SubscriberPackages>(SubscriberPackages.class);
CsvParserSettings parserSettings = new CsvParserSettings(); //many options here, check the tutorial.
parserSettings.setRowProcessor(rowProcessor); //uses the bean processor to handle your input rows
parserSettings.setHeaderExtractionEnabled(true); // extracts header names from the input file.
CsvParser parser = new CsvParser(parserSettings); //creates a parser with your settings.
parser.parse(new FileReader(new File("/path/to/file.csv"))); //all rows parsed here go straight to the bean processor
// The BeanListProcessor provides a list of objects extracted from the input.
List<SubscriberPackages> beans = rowProcessor.getBeans();
Disclosure: I am the author of this library. It's open-source and free (Apache V2.0 license).

How to rename Columns via Lambda function - fasterXML

Im using the FasterXML library to parse my CSV file. The CSV file has the column names in its first line. Unfortunately I need the columns to be renamed. I have a lambda function for this, where I can pass the red value from the csv file in and get the new value.
my code looks like this, but does not work.
CsvSchema csvSchema =CsvSchema.emptySchema().withHeader();
ArrayList<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
MappingIterator<HashMap<String,String>> it = new CsvMapper().reader(HashMap.class)
.with(csvSchema )
.readValues(new File(fileName));
while (it.hasNext())
result.add(it.next());
System.out.println("changing the schema columns.");
for (int i=0; i < csvSchema.size();i++) {
String name = csvSchema.column(i).getName();
String newName = getNewName(name);
csvSchema.builder().renameColumn(i, newName);
}
csvSchema.rebuild();
when i try to print out the columns later, they are still the same as in the top line of my CSV file.
Additionally I noticed, that csvSchema.size() equals 0 - why?
You could instead use uniVocity-parsers for that. The following solution streams the input rows to the output so you don't need to load everything in memory to then write your data back with new headers. It will be much faster:
public static void main(String ... args) throws Exception{
Writer output = new StringWriter(); // use a FileWriter for your case
CsvWriterSettings writerSettings = new CsvWriterSettings(); //many options here - check the documentation
final CsvWriter writer = new CsvWriter(output, writerSettings);
CsvParserSettings parserSettings = new CsvParserSettings(); //many options here as well
parserSettings.setHeaderExtractionEnabled(true); // indicates the first row of the input are headers
parserSettings.setRowProcessor(new AbstractRowProcessor(){
public void processStarted(ParsingContext context) {
writer.writeHeaders("Column A", "Column B", "... etc");
}
public void rowProcessed(String[] row, ParsingContext context) {
writer.writeRow(row);
}
public void processEnded(ParsingContext context) {
writer.close();
}
});
CsvParser parser = new CsvParser(parserSettings);
Reader reader = new StringReader("A,B,C\n1,2,3\n4,5,6"); // use a FileReader for your case
parser.parse(reader); // all rows are parsed and submitted to the RowProcessor implementation of the parserSettings.
System.out.println(output.toString());
//nothing else to do. All resources are closed automatically in case of errors.
}
You can easily select the columns by using parserSettings.selectFields("B", "A") in case you want to reorder/eliminate columns.
Disclosure: I am the author of this library. It's open-source and free (Apache V2.0 license).

Jackson - best way writes a java list to a json array

I want to use jackson to convert a ArrayList to a JsonArray.
Event.java : this is the java bean class with two fields "field1", "field2" mapped as JsonProperty.
My goal is:
Convert
ArrayList<Event> list = new ArrayList<Event>();
list.add(new Event("a1","a2"));
list.add(new Event("b1","b2"));
To
[
{"field1":"a1", "field":"a2"},
{"field1":"b1", "field":"b2"}
]
The way I can think of is:
writeListToJsonArray():
public void writeListToJsonArray() throws IOException {
ArrayList<Event> list = new ArrayList<Event>();
list.add(new Event("a1","a2"));
list.add(new Event("b1","b2"));
OutputStream out = new ByteArrayOutputStream();
JsonFactory jfactory = new JsonFactory();
JsonGenerator jGenerator = jfactory.createJsonGenerator(out, JsonEncoding.UTF8);
ObjectMapper mapper = new ObjectMapper();
jGenerator.writeStartArray(); // [
for (Event event : list) {
String e = mapper.writeValueAsString(event);
jGenerator.writeRaw(usage);
// here, big hassles to write a comma to separate json objects, when the last object in the list is reached, no comma
}
jGenerator.writeEndArray(); // ]
jGenerator.close();
System.out.println(out.toString());
}
I am looking for something like:
generator.write(out, list)
this directly convert the list to json array format and then write it to outputstream "out".
even greedier:
generator.write(out, list1)
generator.write(out, list2)
this will just convert/add in the list1, list2 into a single json array. then write it to "out"
This is overly complicated, Jackson handles lists via its writer methods just as well as it handles regular objects. This should work just fine for you, assuming I have not misunderstood your question:
public void writeListToJsonArray() throws IOException {
final List<Event> list = new ArrayList<Event>(2);
list.add(new Event("a1","a2"));
list.add(new Event("b1","b2"));
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(out, list);
final byte[] data = out.toByteArray();
System.out.println(new String(data));
}
I can't find toByteArray() as #atrioom said, so I use StringWriter, please try:
public void writeListToJsonArray() throws IOException {
//your list
final List<Event> list = new ArrayList<Event>(2);
list.add(new Event("a1","a2"));
list.add(new Event("b1","b2"));
final StringWriter sw =new StringWriter();
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(sw, list);
System.out.println(sw.toString());//use toString() to convert to JSON
sw.close();
}
Or just use ObjectMapper#writeValueAsString:
final ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(list));
In objectMapper we have writeValueAsString() which accepts object as parameter. We can pass object list as parameter get the string back.
List<Apartment> aptList = new ArrayList<Apartment>();
Apartment aptmt = null;
for(int i=0;i<5;i++){
aptmt= new Apartment();
aptmt.setAptName("Apartment Name : ArrowHead Ranch");
aptmt.setAptNum("3153"+i);
aptmt.setPhase((i+1));
aptmt.setFloorLevel(i+2);
aptList.add(aptmt);
}
mapper.writeValueAsString(aptList)

Categories

Resources