Andrew
Andrew

Reputation: 451

Java convert list of string with comma separated values to list of objects

I'd like to convert a json array of person

persons: [
  {"1, Franck, 1980-01-01T00:00:00"},
  {"2, Marc, 1981-01-01T00:00:00"}
]

To a list of Person object using this class:

class Person {
 private Integer id;
 private String name;
 private Date dateOfBirth;

 // getter and setter
}

Would it be possible to use a converter and Java 8 to do it?

public Person convert(String from) {
        String[] data = from.split(",");
        return new Person(Integer.parseInt(data[0]), data[1], new Date(data[2]));
    }

Upvotes: 3

Views: 3735

Answers (2)

Pankaj Singhal
Pankaj Singhal

Reputation: 16053

An Extention of your solution itself & with a bit of abstraction:

List<String> personStr = Arrays.asList("1, Franck, 1980-01-01T00:00:00", "2, Marc, 1981-01-01T00:00:00");

List<Person> persons = personStr.stream()
            .map(Person::new)
            .collect(Collectors.toList());

Where, Person class has a constructor which accepts a string arg to convert it to a Person object, as follows:

public Person(String from) {
    String[] data = from.split(",");
    Arrays.parallelSetAll(data, i -> data[i].trim());
    this.id = Integer.parseInt(data[0]);
    this.name = data[1];
    this.dateOfBirth = new Date(data[2]);
}

Upvotes: 1

Ravindra Ranwala
Ravindra Ranwala

Reputation: 21124

You can do it like so,

Pattern idNumber = Pattern.compile("\\d+");
List<Person> persons = Arrays.stream(from.split("}")).filter(s -> idNumber.matcher(s).find())
    .map(s -> s.substring(s.indexOf("{") + 1)).map(s -> s.split(","))
    .map(a -> new Person(Integer.parseInt(a[0].replaceAll("\"", "")), a[1],
        LocalDateTime.parse(a[2].trim().replaceAll("\"", ""))))
    .collect(Collectors.toList());

First split each string using "}" character, and then filter out invalid tokens, which does not contain a digit. Notice that each valid payload should contain Id number which is a digit. Finally remove any spurious trailing characters occur before the Id digit and map each resulting String to a Person object. At last collect the Person instances into a List.

Notice that I have used LocalDateTime for the dateOfBirth field in the Person class. So the Person class looks like this.

public class Person {
    private final Integer id;
    private final String name;
    private final LocalDateTime dateOfBirth;
    // remainder omitted for the sake of brevity.
}

However as you can see it is always intuitive to use some framework such as Jackson ObjectMapper to get the work done than writing all this. But in this case your Json is malformed so you won't be able to use such a framework unless you fix the json payload structure.

Update

Here's much more elegant Java9 solution.

String regexString = Pattern.quote("{\"") + "(.*?)" + Pattern.quote("\"}");
Pattern pattern = Pattern.compile(regexString);

List<Person> persons = pattern.matcher(from)
        .results()
        .map(mr -> mr.group(1)).map(s -> s.split(", "))
        .map(a -> new Person(Integer.parseInt(a[0]), a[1], LocalDateTime.parse(a[2])))
        .collect(Collectors.toList());

In Java 9, you can now use Matcher#results() to get a Stream<MatchResult>. Here's an excerpt from the documentation.

Returns a stream of match results for each subsequence of the input sequence that matches the pattern. The match results occur in the same order as the matching subsequences in the input sequence.

I would rather recommend you to use Java9 to solve this.

If you need to do it just for a List of String representation of a Person, you may do it like so.

List<String> personStr = Arrays.asList("1, Franck, 1980-01-01T00:00:00", "2, Marc, 1981-01-01T00:00:00");
List<Person> persons = personStr.stream()
        .map(s -> s.replaceAll(" ", "").split(","))
        .map(a -> new Person(Integer.parseInt(a[0]), a[1], LocalDateTime.parse(a[2])))
        .collect(Collectors.toList());

Notice the latter is far more easier than the prior and contains just a subset of the original solution.

Upvotes: 2

Related Questions