title: Unable to read the data back properly
body: <p>I am trying to persist a person class which has a list of pets to a CSV file and read it back to the corresponding objects. I am able to write it properly but unable to read. Please see below -</p>
  
  <p><strong>Person.java</strong></p>
  
  <pre><code>import java.util.ArrayList;
  import java.util.List;
  
  public class Person {
  
  private String name;
  
  private List&lt;Pet&gt; pets;
  
  public Person() {
  }
  
  public Person(final String name, final List&lt;Pet&gt; pets) {
      this.name = name;
      this.pets = pets;
  }
  
  /**
   * @return the name
   */
  public String getName() {
      return name;
  }
  
  /**
   * @return the pets
   */
  public List&lt;Pet&gt; getPets() {
      return pets;
  }
  
  /**
   * @param pets
   *            the pets to set
   */
  public void setAddPet(final Pet pet) {
      if (pets == null) {
          pets = new ArrayList&lt;Pet&gt;();
      }
      pets.add(pet);
  }
  
  /**
   * @param name
   *            the name to set
   */
  public void setName(final String name) {
      this.name = name;
  }
  
  /**
   * @param pets
   *            the pets to set
   */
  public void setPets(final List&lt;Pet&gt; pets) {
      this.pets = pets;
  }
  
  @Override
  public String toString() {
      return String.format("Person [name=%s, pets=%s]", name, pets);
  }
  
  }
  </code></pre>
  
  <p><strong>Pet.java</strong></p>
  
  <pre><code>public class Pet {
  
  private String typeOfAnimal;
  
  private String color;
  
  public Pet() {
  }
  
  public Pet(final String typeOfAnimal, final String color) {
      this.typeOfAnimal = typeOfAnimal;
      this.color = color;
  }
  
  /**
   * @return the color
   */
  public String getColor() {
      return color;
  }
  
  /**
   * @return the typeOfAnimal
   */
  public String getTypeOfAnimal() {
      return typeOfAnimal;
  }
  
  /**
   * @param color
   *            the color to set
   */
  public void setColor(final String color) {
      this.color = color;
  }
  
  /**
   * @param typeOfAnimal
   *            the typeOfAnimal to set
   */
  public void setTypeOfAnimal(final String typeOfAnimal) {
      this.typeOfAnimal = typeOfAnimal;
  }
  
  @Override
  public String toString() {
      return String.format("Pet [typeOfAnimal=%s, color=%s]", typeOfAnimal, color);
  }
  
  }
  </code></pre>
  
  <p><strong>Writer.java</strong></p>
  
  <pre><code>import java.io.FileWriter;
  import java.util.Arrays;
  import java.util.List;
  import org.supercsv.cellprocessor.constraint.NotNull;
  import org.supercsv.cellprocessor.ift.CellProcessor;
  import org.supercsv.io.dozer.CsvDozerBeanWriter;
  import org.supercsv.io.dozer.ICsvDozerBeanWriter;
  import org.supercsv.prefs.CsvPreference;
  
  public class Writer {
  
  private static final String[] HEADERS = new String[] { "name", "pets" };
  
  private static final CellProcessor[] processors = new CellProcessor[] { new NotNull(),
      new NotNull() };
  
  private static final String CSV_FILENAME = "C:\\Users\\Desktop\\Test.csv";
  
  public static void writeWithDozerCsvBeanWriter() throws Exception {
  
      // create the survey responses to write
      final Person person1 = new Person("Dereck", Arrays.asList(new Pet("Dog", 
  "Black")));
      final Person person2 =
          new Person("Gavin", Arrays.asList(new Pet("Squirrel", "Brown"), new Pet("Cat",
                  "White")));
  
      final List&lt;Person&gt; people = Arrays.asList(person1, person2);
  
      ICsvDozerBeanWriter beanWriter = null;
      try {
          beanWriter =
              new CsvDozerBeanWriter(new FileWriter(CSV_FILENAME),
                      CsvPreference.STANDARD_PREFERENCE);
  
          // configure the mapping from the fields to the CSV columns
          beanWriter.configureBeanMapping(Person.class, HEADERS);
  
          // write the header
          beanWriter.writeHeader(HEADERS);
  
          // write the beans
          for (final Person person : people) {
              beanWriter.write(person, processors);
          }
  
      } finally {
          if (beanWriter != null) {
              beanWriter.close();
          }
      }
  }
  }
  </code></pre>
  
  <p><strong>Reader.java</strong></p>
  
  <pre><code>import java.io.FileReader;
  
  import org.supercsv.cellprocessor.Optional;
  import org.supercsv.cellprocessor.constraint.NotNull;
  import org.supercsv.cellprocessor.ift.CellProcessor;
  import org.supercsv.io.CsvBeanReader;
  import org.supercsv.io.ICsvBeanReader;
  import org.supercsv.prefs.CsvPreference;
  
  public class Reader {
  
  private static final String CSV_FILENAME = "C:\\Users\\Desktop\\Test.csv";
  
  /**
   * An example of reading using CsvBeanReader.
   */
  public static void readWithCsvBeanReader() throws Exception {
  
      ICsvBeanReader beanReader = null;
      try {
          beanReader =
              new CsvBeanReader(new FileReader(CSV_FILENAME),
                      CsvPreference.STANDARD_PREFERENCE);
  
          // the header elements are used to map the values to the bean (names must 
  match)
          final String[] header = beanReader.getHeader(true);
  
          // set up the field mapping and processors dynamically
          final String[] fieldMapping = new String[header.length];
          final CellProcessor[] processors = new CellProcessor[header.length];
  
          for (int i = 0; i &lt; header.length; i++) {
              if (i &lt; 1) {
                  // normal mappings
                  fieldMapping[i] = header[i];
                  processors[i] = new NotNull();
              } else {
                  // attribute mappings
                  fieldMapping[i] = "AddPet";
                  processors[i] = new Optional(new ParsePersonPet(header));
              }
          }
  
          Person person;
          while ((person = beanReader.read(Person.class, fieldMapping, processors)) != 
  null) {
                System.out.println(String.format("person=%s", person));
          }
  
      } finally {
          if (beanReader != null) {
              beanReader.close();
          }
      }
  }
  
  }
  </code></pre>
  
  <p><strong>ParsePersonPet.java</strong></p>
  
  <pre><code>import org.supercsv.cellprocessor.CellProcessorAdaptor;
  import org.supercsv.util.CsvContext;
  
  
  public class ParsePersonPet extends CellProcessorAdaptor {
  
  private final String[] header;
  
  public ParsePersonPet(final String[] header) {
      this.header = header;
  }
  
  @Override
  public Object execute(final Object value, final CsvContext context) {
  
      if (value == null) {
          return null;
      }
  
      final Pet pet = new Pet();
      pet.setTypeOfAnimal((String) value);
      return pet;
  }
  
  }
  </code></pre>
  
  <p>Currently, its being written to the csv as below -</p>
  
  <p><img src="https://i.stack.imgur.com/Jgl8D.png" alt="enter image description here"></p>
  
  <p>But when I read it back and print it, it prints as below -</p>
  
  <pre><code>person=Person [name=Dereck, pets=[Pet [typeOfAnimal=[Pet [typeOfAnimal=Dog,  
  color=Black]], color=null]]]
  person=Person [name=Gavin, pets=[Pet [typeOfAnimal=[Pet [typeOfAnimal=Squirrel,    
  color=Brown], Pet [typeOfAnimal=Cat, color=White]], color=null]]]
  </code></pre>
  
  <p>I know the problem is in the <strong>ParsePersonPet.java</strong> at</p>
  
  <pre><code> pet.setTypeOfAnimal((String) value);
  </code></pre>
  
  <p>But the value seems to be coming back as a String as <code>Pet [typeOfAnimal=Dog, color=Black]</code> Do I have to use String Tokenizer and set the appropriate values? It could be quite tedious right? What do I do here?</p>
  
  <p>Thanks</p>
  
  <p><strong>Update:</strong> I got the code to work by changing my ParsePersonPet to below - </p>
  
  <pre><code>import org.supercsv.cellprocessor.CellProcessorAdaptor;
  import org.supercsv.util.CsvContext;
  public class ParsePersonPet extends CellProcessorAdaptor {
  
  private final String[] header;
  
  public ParsePersonPet(final String[] header) {
      this.header = header;
  }
  
  @Override
  public Object execute(final Object value, final CsvContext context) {
  
      if (value == null) {
          return null;
      }
  
      final String str = (String) value;
  
      final Pet pet = new Pet();
      pet.setTypeOfAnimal(getValue("typeOfAnimal", str));
      pet.setColor(getValue("color", str));
  
      return pet;
  }
  
  public String getValue(final String strValueToSearchFor, final String str) {
      if (str.contains(strValueToSearchFor)) {
          final int startIndex =
              str.lastIndexOf(strValueToSearchFor) + strValueToSearchFor.length() + 1;
          int endIndex = str.indexOf(",", startIndex);
          if (endIndex == -1) {
              endIndex = str.indexOf("]", startIndex);
          }
          return str.substring(startIndex, endIndex);
      }
      return null;
  }
  }
  </code></pre>
  
  <p>I need to know how to avoid the setAddpet and use setPets instead and also what do I do if I have a map of pets instead of a list.</p>
  
  <p>Thanks</p>