0

Я пытался сериализовать объект в CSV String, но объект содержит List и @JsonUnwrapped не работает на List объектов.Как правильно сериализовать и десериализовать CSV?

Ожидаемый результат выборки:

color,part.name\n 
red,gearbox\n 
red,door\n 
red,bumper 

Фактический выход:

com.fasterxml.jackson.core.JsonGenerationException: Unrecognized column 'name': 

Вот мой код: (Большинство из них является 2 POJO в)

import com.fasterxml.jackson.annotation.JsonAutoDetect; 
import com.fasterxml.jackson.annotation.JsonFormat; 
import com.fasterxml.jackson.annotation.JsonInclude; 
import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.annotation.JsonPropertyOrder; 
import com.fasterxml.jackson.annotation.JsonRootName; 
import com.fasterxml.jackson.dataformat.csv.CsvMapper; 
import com.fasterxml.jackson.dataformat.csv.CsvSchema; 
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; 
import java.io.IOException; 
import static java.util.Arrays.asList; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class NestedWrapping { 

@JsonRootName("Car") 
@JsonInclude(JsonInclude.Include.NON_DEFAULT) 
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE) 
@JsonPropertyOrder({"color"}) 
public static class Car { 

    @JsonProperty("color") 
    private String color; 

    @JsonFormat(shape = JsonFormat.Shape.STRING) 
    @JacksonXmlElementWrapper(useWrapping = false) 
    private List<Part> parts; 

    public String getColor() { 
     return color; 
    } 

    public void setColor(String color) { 
     this.color = color; 
    } 

    public List<Part> getParts() { 
     return parts; 
    } 

    public void setParts(List<Part> parts) { 
     this.parts = parts; 
    } 

} 

@JsonInclude(JsonInclude.Include.NON_DEFAULT) 
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE) 
@JsonPropertyOrder({ 
    "name" 
}) 
public static class Part { 

    @JsonProperty("name") 
    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

} 

public static void main(String args[]) { 
    try { 
     Car car = new Car(); 
     car.setColor("red"); 
     Part part1 = new Part(); 
     part1.setName("geabox"); 
     Part part2 = new Part(); 
     part2.setName("door"); 
     Part part3 = new Part(); 
     part3.setName("bumper"); 
     car.setParts(asList(part1, part2, part3)); 
     System.out.println("serialized: " + serialize(car, Car.class, true)); 
    } catch (IOException ex) { 
     Logger.getLogger(NestedWrapping.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

public static final synchronized String serialize(final Object object, final Class type, final Boolean withHeaders) throws IOException { 
    CsvMapper csvMapper = new CsvMapper(); 
    CsvSchema csvSchema; 
    if (withHeaders) { 
     csvSchema = csvMapper.schemaFor(type).withHeader(); 
    } else { 
     csvSchema = csvMapper.schemaFor(type).withoutHeader(); 
    } 
    return csvMapper.writer(csvSchema).writeValueAsString(object); 
} 

} 

Ничего, что я пытаюсь, похоже, работает, я читал каждые post о stackoverflow и github об этой теме, но я не могу найти рабочего решения.

Извините за любые бессмысленные аннотации, которые я оставил без причины, и если вы ответите кодом, не стесняйтесь их удалять.

+0

Любая причина вы используете CSV вместо JSON? Насколько я могу судить, у вас много запчастей в одном автомобиле, и я не думаю, что CSV - лучший формат для представления этого –

+0

Я использую XML и JSON, но мне нужно иметь возможность представлять его во всех 3 форматов. Остальные два уже работают. – Hooli

+0

@SotiriosDelimanolis: Готово. Та же концепция, что и база данных 'JOIN' в основном. – Hooli

ответ

4

От ошибок, я хотел бы верить, что у него есть что-то делать с вашей схемой для Car, которая имеет столбцы {"color"}, взятые из @JsonPropertyOrder на Car и не значение "name".

Возможно, вы захотите добавить "parts", но вы получите ту же ошибку, что "name" не является частью этой схемы.

После нескольких изменений вашего кода я смог сериализовать и десериализовать объект Car.

Часть

Здесь, после того, как некоторые другие изменения, что требуется конструктор с одним значением строкового так добавить, что

@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; 
    } 

автомобилей

Здесь вам нужно будет реализует метод, который будет преобразовывать List<Part> в формат, пригодный для чтения в формате CSV.

Такой метод будет выглядеть следующим образом

@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(); 
} 

Кроме того, не забудьте исправить схему в верхней части класса

@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, чтобы взять тип класса в качестве типичного параметра типа вместо явного Class так.

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); 
} 

главный - писатель

Теперь, если вы сериализации Car, вы должны увидеть

color,parts 
red,gearbox;door;bumper 

главная - читатель

И чтение этой строки CSV и перекручивание за 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 
+0

Извинения за задержку ответа. Спасибо, что прояснили все. Я пошел дальше и разместил полное решение ниже для тех, кто ищет рабочее сериализуемое/десериализованное решение CSV. – Hooli

+0

Добро пожаловать. Не похоже, что вы взяли мой комментарий о методе сериализации –

0

Полный рабочий CSV Serialize & Deserialize решение:

import com.fasterxml.jackson.annotation.JsonGetter; 
import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.annotation.JsonPropertyOrder; 
import com.fasterxml.jackson.databind.MappingIterator; 
import com.fasterxml.jackson.dataformat.csv.CsvMapper; 
import com.fasterxml.jackson.dataformat.csv.CsvSchema; 
import java.io.IOException; 
import java.util.ArrayList; 
import static java.util.Arrays.asList; 
import java.util.Iterator; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

public class NestedWrapping { 

    @JsonPropertyOrder({"color", "parts"}) 
    public static class Car { 

     @JsonProperty("color") 
     private String color; 

     @JsonProperty("parts") 
     private List<Part> parts; 

     public String getColor() { 
      return color; 
     } 

     public void setColor(String color) { 
      this.color = color; 
     } 

     public List<Part> getParts() { 
      return parts; 
     } 

     public void setParts(List<Part> parts) { 
      this.parts = parts; 
     } 

     public Car() { 
      this.parts = new ArrayList<>(); 
     } 

     @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(); 
     } 

     @Override 
     public String toString() { 
      return "Car{" + "color=" + color + ", parts=" + parts + '}'; 
     } 

    } 

    @JsonPropertyOrder({ 
     "name" 
    }) 
    public static class Part { 

     @JsonProperty("name") 
     private String name; 

     public Part() { 
     } 

     public Part(String name) { 
      this.name = name; 
     } 

     public String getName() { 
      return name; 
     } 

     public void setName(String name) { 
      this.name = name; 
     } 

     @Override 
     public String toString() { 
      return "Part{" + "name=" + name + '}'; 
     } 

    } 

    public static void main(String args[]) { 
     try { 
      Car car = new Car(); 
      car.setColor("red"); 
      Part part1 = new Part(); 
      part1.setName("geabox"); 
      Part part2 = new Part(); 
      part2.setName("door"); 
      Part part3 = new Part(); 
      part3.setName("bumper"); 
      car.setParts(asList(part1, part2, part3)); 
      String serialized = serialize(car, Car.class, true); 
      System.out.println("serialized: " + serialized); 
      List<Car> deserializedCars = (List) deserialize(serialized, Car.class, true); 
      for (Car deserializedCar : deserializedCars) { 
       System.out.println("deserialized: " + deserializedCar.toString()); 
      } 
     } catch (IOException ex) { 
      Logger.getLogger(NestedWrapping.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    public static final synchronized String serialize(final Object object, final Class type, final Boolean withHeaders) throws IOException { 
     CsvMapper csvMapper = new CsvMapper(); 
     CsvSchema csvSchema; 
     if (withHeaders) { 
      csvSchema = csvMapper.schemaFor(type).withHeader(); 
     } else { 
      csvSchema = csvMapper.schemaFor(type).withoutHeader(); 
     } 
     return csvMapper.writer(csvSchema).writeValueAsString(object); 
    } 

    public static final synchronized List<Object> deserialize(final String csv, final Class type, final Boolean hasHeaders) throws IOException { 
     CsvMapper csvMapper = new CsvMapper(); 
     CsvSchema csvSchema; 
     if (hasHeaders) { 
      csvSchema = csvMapper.schemaFor(type).withHeader(); 
     } else { 
      csvSchema = csvMapper.schemaFor(type).withoutHeader(); 
     } 
     MappingIterator<Object> mappingIterator = csvMapper.readerFor(type).with(csvSchema).readValues(csv); 
     List<Object> objects = new ArrayList<>(); 
     while (mappingIterator.hasNext()) { 
      objects.add(mappingIterator.next()); 
     } 
     return objects; 
    } 

} 
Смежные вопросы