выбор значений по ключам файла json с использованием jackson

#java #jackson

#java #jackson

Вопрос:

Возможно, это самый глупый вопрос на всем сайте. Я новичок в Java и JSON, и мне нужна помощь. Я использую API Jackson. Программа получает файл JSON. Из него мне нужно получить:

  1. Список людей в возрасте от 20 до 30 лет, отсортированных по имени
  2. Уникальный список городов;
  3. Количество людей с возрастным интервалом 0-10, 11-20, 21-30 и так далее.

На данный момент я узнал, как перевести файл json в список java

 import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {

    ObjectMapper mapper = new ObjectMapper();

    try {
        List<Data> data = Arrays.asList(mapper.readValue(Paths.get("C:\data.json").toFile(), Data[].class));


        System.out.println(data);


        } catch (JsonParseException jsonParseException) {
        jsonParseException.printStackTrace();
    } catch (JsonMappingException jsonMappingException) {
        jsonMappingException.printStackTrace();
    } catch (IOException ioException) {
        ioException.printStackTrace();
    }

}
}
  

Был создан класс для чтения файла json

 public class Data {
    private int id;
    private String firstName;
    private String lastName;
    private String dateOfBirth;
    private String city;


public Data(int id, String firstName, String lastName, String dateOfBirth, String city) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.dateOfBirth = dateOfBirth;
        this.city = city;
    }

    public Data() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(String dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "[id = "   id   ", firstName = "   firstName   ", lastName = "   lastName   ", dateOfBirth = "   dateOfBirth   ", city = "   city   "]";
    }
}
  

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

 [
    {
        "id": "1",
        "firstName": "Lesley",
        "lastName": "Bryan",
        "dateOfBirth": "11/28/61",
        "city": "Southampton–Portsmouth"
    },
    {
        "id": "2",
        "firstName": "Edward",
        "lastName": "Houston",
        "dateOfBirth": "10/5/92",
        "city": "Southampton–Portsmouth"
    },
    {
        "id": "3",
        "firstName": "Donald",
        "lastName": "Ross",
        "dateOfBirth": "12/10/79",
        "city": "Glasgow"
    },
    {
        "id": "4",
        "firstName": "Peter",
        "lastName": "Kelly",
        "dateOfBirth": "3/17/04",
        "city": "Birmingham–Wolverhampton"
    },
    {
        "id": "5",
        "firstName": "Anthony",
        "lastName": "McKinney",
        "dateOfBirth": "3/6/68",
        "city": "Liverpool"
    },
    {
        "id": "6",
        "firstName": "David",
        "lastName": "Stewart",
        "dateOfBirth": "4/11/73",
        "city": "Leeds–Bradford"
    },
    {
        "id": "7",
        "firstName": "Christopher",
        "lastName": "Austin",
        "dateOfBirth": "12/28/74",
        "city": "Birmingham–Wolverhampton"
    },
    {
        "id": "8",
        "firstName": "Alvin",
        "lastName": "Hodge",
        "dateOfBirth": "11/25/58",
        "city": "Newcastle upon Tyne–Sunderland"
    },
    {
        "id": "9",
        "firstName": "Gerald",
        "lastName": "Higgins",
        "dateOfBirth": "6/28/55",
        "city": "Liverpool"
    },
    {
        "id": "10",
        "firstName": "Amos",
        "lastName": "Owens",
        "dateOfBirth": "1/16/01",
        "city": "Manchester-Salford"
    },
    {
        "id": "11",
        "firstName": "Christian",
        "lastName": "Bishop",
        "dateOfBirth": "11/14/50",
        "city": "Nottingham"
    },
    {
        "id": "12",
        "firstName": "Robert",
        "lastName": "Caldwell",
        "dateOfBirth": "12/8/80",
        "city": "Manchester-Salford"
    },
    {
        "id": "13",
        "firstName": "Brian",
        "lastName": "Heath",
        "dateOfBirth": "9/23/02",
        "city": "Newcastle upon Tyne–Sunderland"
    },
    {
        "id": "14",
        "firstName": "Mark",
        "lastName": "Anthony",
        "dateOfBirth": "1/8/92",
        "city": "London"
    },
    {
        "id": "15",
        "firstName": "Mark",
        "lastName": "Watson",
        "dateOfBirth": "7/27/91",
        "city": "Nottingham"
    },
    {
        "id": "16",
        "firstName": "Charles",
        "lastName": "Stafford",
        "dateOfBirth": "1/26/90",
        "city": "Birmingham–Wolverhampton"
    },
    {
        "id": "17",
        "firstName": "Steven",
        "lastName": "Merritt",
        "dateOfBirth": "12/4/63",
        "city": "Leeds–Bradford"
    },
    {
        "id": "18",
        "firstName": "John",
        "lastName": "Holmes",
        "dateOfBirth": "4/22/52",
        "city": "Southampton–Portsmouth"
    },
    {
        "id": "19",
        "firstName": "Mervin",
        "lastName": "Lewis",
        "dateOfBirth": "10/27/95",
        "city": "Birmingham–Wolverhampton"
    },
    {
        "id": "20",
        "firstName": "Peter",
        "lastName": "Marsh",
        "dateOfBirth": "12/10/63",
        "city": "Glasgow"
    },
    {
        "id": "21",
        "firstName": "Piers",
        "lastName": "Harrington",
        "dateOfBirth": "4/27/85",
        "city": "London"
    },
    {
        "id": "22",
        "firstName": "Matthew",
        "lastName": "O’Brien’",
        "dateOfBirth": "1/19/59",
        "city": "Manchester-Salford"
    }
]
  

Пожалуйста, скажите мне, в какой последовательности действий выполнить задачу. Еще раз прошу прощения за такое глупое сообщение.
P.S.: Все имена, фамилии и даты из файла json были получены случайным образом.

Ответ №1:

Во-первых, вам необходимо обновить Data класс, чтобы облегчить обработку возрастов и возрастных групп:

  1. Измените тип dateOfBirth to LocalDate , обновите конструктор / getter / предоставьте пользовательский сеттер для обработки дат в 20-м веке
  2. Добавьте методы для получения возраста в годах и возрастной группы в виде строки:
  3. Обновление toString до возраста печати
 class Data {
// ...
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "M/d/yy")
    private LocalDate dateOfBirth;

    public LocalDate getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(LocalDate dob) {
        if (dob.isAfter(LocalDate.now())) {
            dob = dob.minusYears(100);
        }
        this.dateOfBirth = dob;
    }

    @JsonIgnore
    public int getAge() {
        return Period.between(dateOfBirth, LocalDate.now()).getYears();
    }
        
    @JsonIgnore
    public String getAgeGroup() {
        int age = getAge();
        if (age < 11) {
            return "0..10";
        }
        return (age/10*10 1)   ".."   ((age/10   1) * 10);
    }

    @Override
    public String toString() {
        return "[id = "   id   ", age="   getAge()   ", firstName = "   firstName   ", lastName = "   lastName   ", dateOfBirth = "   dateOfBirth   ", city = "   city   "]";
    }
}
  

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

 // get people aged from 20 to 30 sorted by last name/first name
List<Data> age20to30 = data
        .stream()
        .filter(p -> p.getAge() >= 20 amp;amp; p.getAge() < 30)
        .sorted(Comparator.comparing(p -> p.getLastName()   " "   p.getFirstName()))
        .collect(Collectors.toList());
age20to30.forEach(System.out::println);

// get sorted list of unique cities (using TreeSet as a SortedSet)
Set<String> cities = data
        .stream()
        .map(Data::getCity)
        .collect(Collectors.toCollection(TreeSet::new));
cities.forEach(System.out::println);

// get stats by age groups
Map<String, Long> byAges = data
        .stream()
        .collect(Collectors.groupingBy(Data::getAgeGroup, TreeMap::new, Collectors.counting()));
System.out.println(byAges);
  

Вывод

 [id = 14, age=28, firstName = Mark, lastName = Anthony, dateOfBirth = 1992-01-08, city = London]
[id = 2, age=27, firstName = Edward, lastName = Houston, dateOfBirth = 1992-10-05, city = Southampton–Portsmouth]
[id = 19, age=24, firstName = Mervin, lastName = Lewis, dateOfBirth = 1995-10-27, city = Birmingham–Wolverhampton]
[id = 15, age=29, firstName = Mark, lastName = Watson, dateOfBirth = 1991-07-27, city = Nottingham]

Birmingham–Wolverhampton
Glasgow
Leeds–Bradford
Liverpool
London
Manchester-Salford
Newcastle upon Tyne–Sunderland
Nottingham
Southampton–Portsmouth

{11..20=3, 21..30=4, 31..40=3, 41..50=3, 51..60=4, 61..70=5}
  

Комментарии:

1. Не удается создать экземпляр com.testsample.Data (не существует создателей, подобных конструктору по умолчанию): не удается выполнить десериализацию из значения объекта (нет создателя на основе делегата или свойства) в [Источник: (Файл); строка: 3, столбец: 3] (через цепочку ссылок: java.lang. Объект [][0])

2. Похоже, существует проблема со структурой файла JSON. Я дважды проверил синтаксический анализ данных, приведенных выше, в виде строки и внутри файла, и он работал нормально.