У меня есть уникальный НАБОР объектов местоположения с такими данными, как
location 1: "USA", "AZ", "Phoenix"
location 2: "USA", "AZ", "Scottsdale"
location 3: "USA", "AZ", "Peoria"
Front end needs following json structure to render UI:
"USA"-> [{"AZ" -> ["Phoenix", "Scottsdale","Peoria"]},
{"MD" -> ["Baltimore", "Gaithersburg","OwingsMills"]}
]
Java POJO для Location.java
Я написал код, который представляет собой набор строк для итерации по набору местоположений и создания объектов страны, содержащих набор объектов состояния, содержащих набор объектов города, с использованием объекта FacetsGeo и генерации json из этих моделей данных.
Я думаю, что может быть лучший способ сделать это: возможно, с Java 8 Streaming API.
Любая помощь приветствуется, как я уже сказал выше, это пример данных о том, как построены плоские местоположения.
public class Location {
private final String country;
private final String state;
private final String city;
public Location(final String country, final String state, final
String city) {
this.country = country;
this.state = state;
this.city = city;
}
public String getCountry() {
return country;
}
public String getState() {
return state;
}
public String getCity() {
return city;
}
@Override
public boolean equals(Object thatLocation) {
if (thatLocation == this) return true;
if (!(thatLocationCriteria instanceof Location)) {
return false;
}
Location location = (Location) thatLocation;
return Objects.equals(this.country, location.country) &&
Objects.equals(this.state, location.state) &&
Objects.equals(this.city, location.city);
}
@Override
public int hashCode() {
return Objects.hash(this.country, this.state, this.city);
}
}
FacetsGeo.java
public class FacetsGeo {
private String label;
private String value;
private String type;
private String subtype;
private List<FacetsGeo> childFacetsGeo;
}
То, что я пытался создать выше структуры данных внешнего интерфейса:
` List<FacetsGeo> facetsList = new ArrayList<FacetsGeo>();
Optional<locations> locationsOptional = Optional.ofNullable(locations);
if (locationsOptional.isPresent()) {
//locations
for (final Location location : locationsOptional.get().getLocations()) {
FacetsGeo facetCountry = new FacetsGeo();
if (location.getCountry() != null
&& location.getCountry().equalsIgnoreCase("United States")
&& location.getState() != null) {
boolean countryExists = false;
for(FacetsGeo facetGeo: facetsList) {
if (facetGeo.getType() != null && facetGeo.getSubtype() != null
&& facetGeo.getType().equalsIgnoreCase("location")
&& facetGeo.getSubtype().equalsIgnoreCase("country")
&& facetGeo.getValue().equalsIgnoreCase(location.getCountry())) {
facetCountry = facetGeo;
if (facetCountry.getSubCriteria() == null) {
facetCountry.setSubCriteria(new ArrayList<FacetsGeo>());
}
countryExists = true;
break;
}
}
if (!countryExists) {
facetCountry.setLabel(location.getCountry());
facetCountry.setValue(location.getCountry());
facetCountry.setType("location");
facetCountry.setSubtype("country");
FacetsGeo subcriteriaState = new FacetsGeo();
subcriteriaState.setLabel(location.getState());
subcriteriaState.setValue(location.getState());
subcriteriaState.setType("location");
subcriteriaState.setSubtype("state");
FacetsGeo subcriteria = new FacetsGeo();
subcriteria.setLabel(location.getCity());
subcriteria.setValue(location.getCity());
subcriteria.setType("location");
subcriteria.setSubtype("city");
subcriteriaState.setSubCriteria(new ArrayList<FacetsGeo>());
subcriteriaState.getSubCriteria().add(subcriteria);
facetCountry.setSubCriteria(new ArrayList<FacetsGeo>());
facetCountry.getSubCriteria().add(subcriteriaState);
searchBarFacetsList.add(searchBarFacetCountry);
} else {
FacetsGeo subcriteriaCity = new FacetsGeo();
subcriteriaCity.setLabel(location.getCity());
subcriteriaCity.setValue(location.getCity());
subcriteriaCity.setType("location");
subcriteriaCity.setSubtype("city");
FacetsGeo facetStateToAdd = new FacetsGeo();
boolean stateExists = false;
for(FacetsGeo facetState: facetCountry.getSubCriteria()) {
if (facetState.getType() != null && facetState.getSubtype() != null
&& facetState.getType().equalsIgnoreCase("location")
&& facetState.getSubtype().equalsIgnoreCase("state")
&& facetState.getValue().equalsIgnoreCase(location.getState())) {
facetStateToAdd = facetState;
if (facetStateToAdd.getSubCriteria() == null) {
facetStateToAdd.setSubCriteria(new ArrayList<FacetsGeo>());
}
stateExists = true;
break;
}
}
if (!stateExists) {
facetStateToAdd.setLabel(location.getState());
facetStateToAdd.setValue(location.getState());
facetStateToAdd.setType("location");
facetStateToAdd.setSubtype("state");
if (facetStateToAdd.getSubCriteria() == null) {
facetStateToAdd.setSubCriteria(new ArrayList<SearchBarFacets>());
}
facetStateToAdd.getSubCriteria().add(subcriteriaCity);
facetCountry.getSubCriteria().add(facetStateToAdd);
} else {
facetStateToAdd.getSubCriteria().add(subcriteriaCity);
facetCountry.getSubCriteria().add(facetStateToAdd);
}
}
}
}
}`
Зачем вам массив состояний? Разве { "USA": { "AZ": ["Phoenix", "Scottsdale","Peoria"], "MD": ["Baltimore", "Gaithersburg","OwingsMills"] } } не был бы лучше JSON?
Спасибо @Andreas, я попробую ваше решение.
метка: «США», значение: «США», тип: «Местоположение», подтип: «Страна», childFacetsGeo: состояния List<FacetsGeo>.




Для решения потоковой передачи Java 8 это можно сделать, как показано ниже.
Это конкретное решение не генерирует точно такой же JSON, как показано в вопросе, потому что я не думаю, что массив объектов состояния с 1 ключом на объект, именующий состояние, является хорошей структурой JSON.
Если JSON должен быть таким, как показано в вопросе, то это решение даст хороший старт.
Set<Location> locationSet = Set.of(
new Location("USA", "AZ", "Phoenix"),
new Location("USA", "AZ", "Scottsdale"),
new Location("USA", "AZ", "Peoria"),
new Location("USA", "MD", "Baltimore"),
new Location("USA", "MD", "Gaithersburg"),
new Location("USA", "MD", "OwingsMills"),
new Location("CA", "ON", "Toronto"));
Map<String, Map<String, List<String>>> countryMap = locationSet.stream()
.collect(Collectors.groupingBy(Location::getCountry, TreeMap::new,
Collectors.groupingBy(Location::getState, TreeMap::new,
Collectors.mapping(Location::getCity, Collectors.toList()))));
System.out.println(JSONWriter.valueToString(countryMap));
Выход
{"CA":{"ON":["Toronto"]},"USA":{"AZ":["Phoenix","Scottsdale","Peoria"],"MD":["OwingsMills","Baltimore","Gaithersburg"]}}
Set.of — это Java9++.
@Andreas, не могли бы вы объяснить, что происходит под капотом этого нового API, и есть ли способ получить данные о местоположении в FacetsGeo (любопытно узнать, возможно это или нет)
Как вы сопоставляете Location и FacetsGeo? Что означают такие поля, как метка, значение и т. д. в FacetsGeo? что ты уже испробовал? Перед публикацией вопроса ознакомьтесь с этим: stackoverflow.com/help/минимально-воспроизводимый-пример