Struktura Hashmap do Json

0

Witam,
chciałbym ze struktury Hashmap

        var list = new HashMap<String, String>();
        list.put("company.name", "IBM");
        list.put("company.tag.0.name", "computer");
        list.put("company.tag.1.name", "cpu");
        list.put("company.address.country", "USA");
        list.put("company.category.0", "aaa");
        list.put("company.category.1", "bbb");

Zrobić strukturę obiektową json z zagłębieniami.
Czyli z powyższego będzie:

{"company": { "name": "IBM", "tag": [{"name": "computer"}, {"name": "cpu"}], "address": {"country": "USA"}, "category": ["aaa", "bbb"] }}

Czy jest jakiś prosty sposób, żeby to uzyskać?

0

Biblioteki Gson lub Jackson.

EDIT: zle spojrzałem - na wejściu musisz mieć „mapę map” z prostymi kluczami (albo po prostu własne klasy), u Ciebie są ścieżki. To nie wiem tak z głowy :)

0

Out of the box na pewno nie, bo to przeciez jakiś customowy format. Zresztą mógłbyś mieć tam wrzucone coś z czego nie da się wcale zrobić jsona, np.

list.put("company.category.0", "aaa");
list.put("company.category.1", "bbb");
list.put("company.category", "ccc");

Ale napisać kod który przerobi to na zagnieżdżone mapy/listy nie powinno być ciężko.

0

Znalazłem coś takiego > https://github.com/json-path/JsonPath - zawsze tego string'a mogę przerobić na taką strukturę, która będzie interpretować ta klasa.

1

Można na piechotę. Lecisz po każdym kluczu i tworzysz mapę map - podobnie jak buduje się drzewo TRIE. Czyli dla x.y.z lecisz od x do z tworząc po kolei brakujące węzły w swojej strukturze. Na koniec prosta serializacja mapy i gotowe.

0
Shalom napisał(a):

Out of the box na pewno nie, bo to przeciez jakiś customowy format.

Nie do końca customowy. Mi to wygląda na propertiesy Javowe. Czyli można z jednej strony wczytać za pomocą https://github.com/FasterXML/jackson-dataformats-text i potem wypluć do Jsona. Ewentualnie można użyć w tym celu HOCON bo ten format jest nakładką na jsona i properties jednocześnie, ale po sparsowaniu można dane wypisać jako json.

0

Taka trywialna implementacja:

import json


def main():
    inputs = {}
    inputs["company.name"] = "IBM"
    inputs["company.tag.0.name"] = "computer"
    inputs["company.tag.1.name"] = "cpu"
    inputs["company.address.country"] = "USA"
    inputs["company.category.0"] = "aaa"
    inputs["company.category.1"] = "bbb"
    print(inputs)
    pass

    result = {}
    for path, value in inputs.items():
        current = result
        for component in path.split(".")[:-1]:
            if component not in current:
                current[component] = {}
            current = current[component]
        last_node = path.split(".")[-1]
        current[last_node] = value
    print(json.dumps(result))


main()

Nie idealna bo robi mapę z tej listy, ale zaraz się to zateguje :D

edit:
Opcja z listami:

import collections
import json


def main():
    inputs = collections.OrderedDict()
    inputs["company.name"] = "IBM"
    inputs["company.tag.0.name"] = "computer"
    inputs["company.tag.1.name"] = "cpu"
    inputs["company.address.country"] = "USA"
    inputs["company.category.0"] = "aaa"
    inputs["company.category.1"] = "bbb"
    inputs["company.category.0"] = "aaa"
    inputs["company.category.1"] = "bbb"
    print(inputs)
    pass

    result = {}
    for path, value in inputs.items():
        current = result
        all_components = path.split(".")
        components = all_components[:-1]
        for i, component in enumerate(components):
            if component.isdigit():
                index = int(component)
                if len(current) <= index:
                    current.append({})
                current = current[index]
            else:
                if component not in current:
                    if len(all_components) > i + 1 and all_components[i + 1].isdigit():
                        current[component] = []
                    else:
                        current[component] = {}
                current = current[component]
        last_node = path.split(".")[-1]
        if last_node.isdigit():
            current.append(value)
        else:
            current[last_node] = value

    print(json.dumps(result))


main()

Niestety mniej elegancka, bo trzeba sprawdzać czy musimy dodać listę czy mapę :/

0

Wracam do tego wątku, gdyż mam problem z przekonwertowaniem powyższego kodu na Jave.
Poniżej mój kod i zaznaczone, gdzie mam problem.

Czy da się tego python'a zmienić na javę - proszę o pomoc.


import java.util.*;
public class HelloTest {

     public static void main(String []args){
        var list = new HashMap<String, Object>();
        list.put("company.name", "IBM");
        list.put("company.tag.0.name", "computer");
        list.put("company.tag.1.name", "cpu");
        list.put("company.address.country", "USA");
        list.put("company.category.0", "aaa");
        list.put("company.category.1", "bbb");

        var result = convertPathsToHashMap(list);
    }

    public HashMap<String, Object> convertPathsToHashMap(Map<String, Object> input) {
        var result = new HashMap<String, Object>();
        input.forEach((path, value) -> {
            var current = result;
            var allComponents = new ArrayList<>(Arrays.asList(path.split("\\.")));
            allComponents.remove(allComponents.size() - 1);
            var i = 0;
            for (var component : allComponents) {
                if (component.matches("\\d+")) {
                    Integer index = Integer.valueOf(component);
                    if (current.size() <= index) {
                        current.put(component, new HashMap<>());
                    }
                    current = current.put(component, current.get(index)); // << tu jest problem z typem
                } else {
                    if (current.get(component) == null) {
                        if (allComponents.size() > i + 1 && allComponents.get(i + 1).matches("\\d+")) {
                            current.put(component, new ArrayList<>());
                        } else {
                            current.put(component, new HashMap<>());
                        }
                        current = current.get(component); // << tu jest problem z typem
                    }
                }

                var lastElement = allComponents.get(allComponents.size() - 1);
                if (component.matches("\\d+")) {
                    current.put(component, value);
                } else {
                    current.put(lastElement, value);
                }
                i++;
            }
        });
        return result;
     }
}

Edit:
Naprawdę, nikt nie pomoże?

Jestem wdzięczny Shalom za rozwiązanie, bo chociaż nakierował jak to mniej więcej ma być, ale..., pisząc w kategorii Java oczekiwałem pomocy właśnie w tym języku.

To jest tak jakbym na forum tłumaczeń prosił o pomoc w przetłumaczeniu 3 zdań w języku hiszpańskim, a otrzymał w języku francuskim....
Później próbował przetłumaczyć na podstawie francuskiego na hiszpański, ale brakuje mi paru wyrazów/wskazówek, żeby to było poprawne.

0

No bo masz tam mapę z Objectami więc musisz je rzutować na coś, skąd ma być wiadomo czy to Mapa czy Lista? No i przetłumaczyłeś to blędnie. Przecież te instrukcje mapują się generalnie 1:1, widzisz u mnie coś jak twoje current = current.put(component, current.get(index)); ? Bo ja widzę current = current[index]

Naprawdę, nikt nie pomoże?

O jejku, po 20 minutach nikt nie odpowiedział i juz jakieś ranty robisz o_O WTF.

To jest tak jakbym na forum tłumaczeń prosił o pomoc w przetłumaczeniu 3 zdań w języku hiszpańskim, a otrzymał w języku francuskim....

Algorytm to algorytm.

Ale tak na marginesie, to ja bym takiego kodu raczej nigdzie na produkcje nie wrzucał :D

import java.util.*;

public class HelloTest {

    public static void main(String[] args) {
        var list = new TreeMap<String, Object>();
        list.put("company.name", "IBM");
        list.put("company.tag.0.name", "computer");
        list.put("company.tag.1.name", "cpu");
        list.put("company.address.country", "USA");
        list.put("company.category.0", "aaa");
        list.put("company.category.1", "bbb");
        var result = convertPathsToHashMap(list);
        System.out.println(result);
    }

    public static HashMap<String, Object> convertPathsToHashMap(Map<String, Object> input) {
        var result = new HashMap<String, Object>();
        input.forEach((path, value) -> {
            Object current = result;
            var allComponents = new ArrayList<>(Arrays.asList(path.split("\\.")));
            var components = allComponents.subList(0, allComponents.size() - 1);
            var i = 0;
            for (var component : components) {
                if (component.matches("\\d+")) {
                    int index = Integer.parseInt(component);
                    List<Object> realCurrent = (List<Object>) current;
                    if (realCurrent.size() <= index) {
                        realCurrent.add(new HashMap<>());
                    }
                    current = realCurrent.get(index);
                } else {
                    Map<String, Object> realCurrent = (Map<String, Object>) current;
                    if (!realCurrent.containsKey(component)) {
                        if (allComponents.size() > i + 1 && allComponents.get(i + 1).matches("\\d+")) {
                            realCurrent.put(component, new ArrayList<>());
                        } else {
                            realCurrent.put(component, new HashMap<>());
                        }
                    }
                    current = realCurrent.get(component);
                }
                i++;
            }
            var lastElement = allComponents.get(allComponents.size() - 1);
            if (lastElement.matches("\\d+")) {
                List<Object> realCurrent = (List<Object>) current;
                realCurrent.add(value);
            } else {
                Map<String, Object> realCurrent = (Map<String, Object>) current;
                realCurrent.put(lastElement, value);
            }
        });
        return result;
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1