Reputation: 451
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
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
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