3

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]));
    }
2
  • You should have a look at json parsers like jacksonxml for such tasks. Commented Aug 11, 2018 at 0:17
  • The json array is not correct. What is that object inside json array - a string or an json object? Commented Aug 11, 2018 at 14:09

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Ravindra, it makes total sense! However would you have any idea how to do it if you had a List<String> as a parameter to convert to a List<Person> ?
@Andrew Show me your input list, and then I can update the answer.
Given I am using SpringBoot, I was thinking of using a wrapper so I could map the RequestBody to this wrapper automatically and then convert it to a List<Person>: public class PersonsWrapper { private List<String> persons; } So each String in this list would look like this: "2, Marc, 1981-01-01T00:00:00"
Mate you're awesome! I haven't used java for a while, it's so nice to be able to convert it this way!
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.