How to serialize object to CSV file?
First, serialization is writing the object to a file 'as it is'. AFAIK, you cannot choose file formats and all. The serialized object (in a file) has its own 'file format'
If you want to write the contents of an object (or a list of objects) to a CSV file, you can do it yourself, it should not be complex.
Looks like Java CSV Library can do this, but I have not tried this myself.
EDIT: See following sample. This is by no way foolproof, but you can build on this.
//European countries use ";" as
//CSV separator because "," is their digit separator
private static final String CSV_SEPARATOR = ",";
private static void writeToCSV(ArrayList<Product> productList)
{
try
{
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("products.csv"), "UTF-8"));
for (Product product : productList)
{
StringBuffer oneLine = new StringBuffer();
oneLine.append(product.getId() <=0 ? "" : product.getId());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.getName().trim().length() == 0? "" : product.getName());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.getCostPrice() < 0 ? "" : product.getCostPrice());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.isVatApplicable() ? "Yes" : "No");
bw.write(oneLine.toString());
bw.newLine();
}
bw.flush();
bw.close();
}
catch (UnsupportedEncodingException e) {}
catch (FileNotFoundException e){}
catch (IOException e){}
}
This is product (getters and setters hidden for readability):
class Product
{
private long id;
private String name;
private double costPrice;
private boolean vatApplicable;
}
And this is how I tested:
public static void main(String[] args)
{
ArrayList<Product> productList = new ArrayList<Product>();
productList.add(new Product(1, "Pen", 2.00, false));
productList.add(new Product(2, "TV", 300, true));
productList.add(new Product(3, "iPhone", 500, true));
writeToCSV(productList);
}
Hope this helps.
Cheers.
Serialize and Deserialize CSV file as Stream
You are getting this error because the serializer does not know how to instantiate your FileParameter
class. It prefers to use a default constructor if possible. It can use a parameterized constructor in some cases, if you give it a hint as to which one by marking it with a [JsonConstructor]
attribute and all the constructor parameters match up to properties in the JSON object. However, that won't work in your case because all of your constructors expect a Stream
and you require special handling for that.
To solve this you need a way for the serializer to instantiate your class without the stream and then use the converter to create the stream. You said you tried adding a default constructor, but then the stream was null. The reason it did not work is because all of your setters are private. With the default constructor, the serializer was able to instantiate the FileParameter
, but then it could not populate it.
There are a couple of ways to make it work.
Solution 1 - modify the FileParameter class
- Add a default constructor to the
FileParameter
class as you did before. It can be private if you also mark it with[JsonConstructor]
. - Add
[JsonProperty]
attributes to all of the private-set properties that need to be populated from the JSON. This will allow the serializer to write to the properties even though they are private.
So your class would look like this:
public partial class FileParameter
{
public FileParameter(System.IO.Stream data)
: this(data, null)
{
}
public FileParameter(System.IO.Stream data, string fileName)
: this(data, fileName, null)
{
}
public FileParameter(System.IO.Stream data, string fileName, string contentType)
{
Data = data;
FileName = fileName;
ContentType = contentType;
}
[JsonConstructor]
private FileParameter()
{
}
[JsonProperty]
public System.IO.Stream Data { get; private set; }
[JsonProperty]
public string FileName { get; private set; }
[JsonProperty]
public string ContentType { get; private set; }
}
Here is a working demo: https://dotnetfiddle.net/371ggK
Solution 2 - use a ContractResolver
If you cannot easily modify the FileParameter
class because it is generated or you don't own the code, you can use a custom ContractResolver
to do the same thing programmatically. Below is the code you would need for that.
public class CustomContractResolver : DefaultContractResolver
{
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
JsonObjectContract contract = base.CreateObjectContract(objectType);
if (objectType == typeof(FileParameter))
{
// inject a "constructor" to use when creating FileParameter instances
contract.DefaultCreator = () => new FileParameter(null);
// make the private properties writable
string[] propNames = new string[]
{
nameof(FileParameter.Data),
nameof(FileParameter.FileName),
nameof(FileParameter.ContentType),
};
foreach (JsonProperty prop in contract.Properties.Where(p => propNames.Contains(p.UnderlyingName)))
{
prop.Writable = true;
}
}
return contract;
}
}
To use the resolver, add it to the JsonSerializerSettings
along with the StreamStringConverter
:
var obj = JsonConvert.DeserializeObject<BulkLeadRequest>(serializedObject,
new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(),
Converters = new List<JsonConverter> { new StreamStringConverter() }
});
Working demo: https://dotnetfiddle.net/VHf359
By the way, in the WriteJson
method of your StreamStringConverter
, I noticed you are casting the value
to a FileStream
even though the CanConvert
method says it can handle any Stream
. You can fix it by changing this line:
FileStream valueStream = (FileStream)value;
to this:
Stream valueStream = (Stream)value;
Write java objects to CSV file
If you want to write into a CSV
file then you don't need to implement Serializable
interface. With Serialization you can not write csv
file. Serialization process write object state into .sar
file. You may consider to use some CSV
library or you may write it. You may check this tutorial.
Generating CSV file from object in java
You might have got the answer if googled it.
It already has answer here : Object to CSV
Using super csv : Using super csv to write in csv from object
How do I serialize & deserialize CSV properly?
From the error, I would like to believe that it has something to do with your schema for a Car
, which has the columns of {"color"}
taken from @JsonPropertyOrder
on Car
and not a "name"
value.
You probably want to add "parts"
in there, but you would get the same error that "name"
is not part of that schema.
After a few changes to your code, I was able to serialize and deserialize a Car
object.
Part
Here, after some other changes it needed a constructor with a single String value, so add that
@JsonPropertyOrder({"name"})
public static class Part {
@JsonProperty("name")
private String name;
public Part() {
this("");
}
public Part(String partJSON) {
// TODO: Unserialize the parameter... it is a serialized Part string...
this.name = partJSON;
}
Car
Here, you will need to implement a method that will convert the List<Part>
into a CSV-readable format manually.
Such a method would look like this
@JsonGetter("parts")
public String getPartString() {
String separator = ";";
StringBuilder sb = new StringBuilder();
Iterator<Part> iter = this.parts.iterator();
while (iter.hasNext()) {
Part p = iter.next();
sb.append(p.getName());
if (iter.hasNext())
sb.append(separator);
}
return sb.toString();
}
Also, don't forget to fix the schema at the top of the class
@JsonPropertyOrder({"color", "parts"})
public static class Car {
@JsonProperty("color")
private String color;
@JsonProperty("parts")
private List<Part> parts;
public Car() {
this.parts = new ArrayList<>();
}
serialize
You can change your serialize
method to take the type of the class as a generic type parameter instead of an explicit Class
like so.
public static final synchronized <T> String serialize(final T object, final Boolean withHeaders) throws IOException {
CsvMapper csvMapper = new CsvMapper();
CsvSchema csvSchema = csvMapper.schemaFor(object.getClass());
if (withHeaders) {
csvSchema = csvSchema.withHeader();
} else {
csvSchema = csvSchema.withoutHeader();
}
return csvMapper.writer(csvSchema).writeValueAsString(object);
}
main - writer
Now, if you serialize a Car
, you should see
color,parts
red,gearbox;door;bumper
main - reader
And reading that CSV string and looping over the Car.getParts()
Car car = mapper.readerFor(Car.class).with(csvSchema).readValue(csv);
for (Part p : car.getParts()) {
System.out.println(p.getName());
}
gearbox
door
bumper
Related Topics
Parsing JSON Array Within JSON Object
Displaying Fancy Equations with Java
Htmlunit Doesn't Wait for JavaScript
Change Database Schema Used by Spring Boot
When and How Are Classes Garbage Collected in Java
Find the Most Popular Element in Int[] Array
Arrays.Fill with Multidimensional Array in Java
On-The-Fly, In-Memory Java Code Compilation for Java 5 and Java 6
Differencebetween Lowagie and Itext
How to Set a Long Java Classpath in Windows
What's an Example of Duck Typing in Java
Running Java Gives "Error: Could Not Open 'C:\Program Files\Java\Jre6\Lib\Amd64\Jvm.Cfg'"
Regex That Will Match a Java Method Declaration
Invalid Syntax Error "Type= Myisam" in Ddl Generated by Hibernate
How to Do N-Level Nested Loops in Java
How to Deal with the Urisyntaxexception