Реструктуризация файла JSON в JAVA

У меня есть следующий образец из файла JSON:

[
{
  "0":
  {
    "File":"file1.java",
    "Class":"com.ETransitionActionType",
    "Method":"values",
    "Annotation":"Not Found"
  }
},
{
  "1":
  {
    "File":"file2.java",
    "Class":"com.ETransitionParams",
    "Method":"values",
    "Annotation":"Not Found"
  }
},
{
  "2":
  {
    "File":"file3.java",
    "Class":"com.phloc.commons.id.IHasID",
    "Method":"getID",
    "Annotation":"Not Found"
  }
},
{
  "4":
  {
    "File":"file3.java",
    "Class":"com.ExecuteTransitionActionHandler",
    "Method":"createBadRequestResponse",
    "Annotation":"Not Found"
  }
},
{
  "5":
  {
    "File":"file3.java",
    "Class":"com.ExecuteTransitionActionHandler",
    "Method":"extractParametersFromAction",
    "Annotation":"Not Found"
  }
}]

Как я могу реструктурировать этот файл с помощью java, чтобы он выглядел так:

[{
    "file1.java": {
        "com.ETransitionActionType": {
            "values": {
                "Annotation": "Not Found"
            }
        }
    }
},
{
    "file2.java": {
        "com.ETransitionParams": {
            "values": {
                "Annotation": "Not Found"
            }
        }
    }
},
{
    "file3.java": {
        "com.phloc.commons.id.IHasID": {
            "getID": {
                "Annotation": "Not Found"
            }
        },
        "com.ExecuteTransitionActionHandler": {
            "getID": {
                "Annotation": "Not Found"
            },
            "extractParametersFromAction": {
                "Annotation": "Not Found"
            }
        }
    }
}
]

т.е. просматривая файл JSON, выполняя поиск в нем, и везде, где атрибут «Файл» имеет одинаковое значение (например, «file3.java»), мы перечисляем все соответствующие классы и методы внутри, и то же самое относится к атрибуту «Класс». , если у него такое же имя, мы перечисляем все методы внутри него (это похоже на сравнение и сортировку значений для атрибутов «Файл» и «Класс»). Я начал с простой библиотеки JSON и написал, как код ниже, но не знаю, что делать дальше!

Object object = (JSONArray)parser.parse(new FileReader("rawOutput.json"));            
JSONArray jsonArray =  (JSONArray) object;
for(int i = 0; i < jsonArray.size(); i++) {
    System.out.println(jsonArray.get(i));
    JSONObject jsonObject = (JSONObject)jsonArray.get(i);
    String c = jsonObject.get("" + i + "").toString();
}

Любые идеи? Ваша помощь очень ценится !!!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
464
3

Ответы 3

Вы можете создать карту карт для представления вашей группировки по «Файлу» и «Классу» для вашего списка (внутренних) объектов JSON. Это может быть похоже на

final Function<JSONObject, String> fileFunction = (JSONObject jsonObject) -> jsonObject.getString("File");
final Function<JSONObject, String> classFunction = (JSONObject jsonObject) -> jsonObject.getString("Class");
final Map<String, Map<String, List<JSONObject>>> groupedJsonObjects = jsonObjects.stream()
            .collect(Collectors.groupingBy(fileFunction, Collectors.groupingBy(classFunction)));
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Foo {
    public static void main(String... args) throws IOException {
        String json = formatJson(new FileReader("rawOutput.json"));
        System.out.println(json);
    }

    public static String formatJson(Reader reader) throws IOException {
        // group array items by fileName
        final Function<List<Map<String, Object>>, Map<String, List<Object>>> groupByFileName =
                data -> data.stream().collect(Collectors.groupingBy(map -> (String)map.get("File"), TreeMap::new,
                        Collectors.mapping(Function.identity(), Collectors.toList())));

        // convert source item structure into required
        final Function<Map.Entry<String, List<Object>>, Map<String, Object>> convert = entry -> {
            Map<String, Map<String, Map<String, String>>> tmp = new LinkedHashMap<>();

            entry.getValue().stream()
                    .map(value -> (Map<String, String>)value)
                    .forEach(map -> {
                        Map<String, Map<String, String>> classes = tmp.computeIfAbsent(map.get("Class"), cls -> new TreeMap<>());
                        Map<String, String> methods = classes.computeIfAbsent(map.get("Method"), method -> new TreeMap<>());

                        map.entrySet().stream()
                                .filter(e -> !"Class".equals(e.getKey()) && !"Method".equals(e.getKey()) && !"File".equals(e.getKey()))
                                .forEach(e -> methods.put(e.getKey(), e.getValue()));
                    });

            return Collections.singletonMap(entry.getKey(), tmp);
        };

        ObjectMapper mapper = new ObjectMapper();

        // read json as array of Maps
        List<Map<String, Object>> data = Arrays.stream(mapper.readValue(reader, Map[].class))
                .map(map -> map.values().iterator().next())
                .map(item -> (Map<String, Object>)item)
                .collect(Collectors.toList());

        return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(groupByFileName.apply(data).entrySet().stream()
                .map(convert).collect(Collectors.toList()));
    }
}

Большое спасибо за ответ! Не могли бы вы указать, как я могу использовать ваш метод с приведенным выше фрагментом кода? Как используется параметр "String json" в приведенном выше методе? а какой импорт вы использовали?

Sarah 18.10.2018 13:57

См. Мой обновленный пример. Я считаю, что new FileReader("rawOutput.json") не возвращает исключений и находит нужный файл.

oleg.cherednik 18.10.2018 14:03

Спасибо за ваш быстрый ответ! Ваш код работает, но в нем есть ошибка, заключающаяся в том, что если в одном классе имеется более одного метода, он перечисляет только один метод внутри атрибута класса.

Sarah 18.10.2018 15:01

Я написал код, чтобы сделать то, что вам нужно, но сначала вы должны добавить эту библиотеку в свой проект, если у вас еще нет библиотека org.json.zip, потому что у меня не было библиотеки для анализа текстов Json, поэтому я использовал эту библиотеку для форматирования Данные Json, и мне очень жаль, если вы не полностью понимаете код, потому что ваш запрос не так прост, как вы знаете, и я создал три функции, чтобы получить результат, и хотя я написал несколько комментариев, чтобы их было легко понять, это код:-

Edit

...
import org.json.*;
...
...
public static void main(String[] args) throws JSONException {
    System.out.println(getFormattedJson("json text"));
}

private static String getFormattedJson(String text) throws JSONException{
    JSONArray result = new JSONArray();
    JSONArray jsonArray = null;

    //get the json array
    jsonArray = new JSONArray(text);

    //loop through items in the array and insert them formatted to the result
    for (int i = 0; i < jsonArray.length(); i++) {
        //get object inside the number
        JSONObject object = getJsonChild(jsonArray.getJSONObject(i));

        //get these attributes
        String file = object.getString("File");
        String clas = object.getString("Class");
        String meth = object.getString("Method");
        String anno = object.getString("Annotation");

        //create a custom type of the object's attributes
        Map<String, String> map = new HashMap<>();
        map.put("Annotation", anno);
        Map<String, Object> map1 = new HashMap<>();
        map1.put(meth, map);
        Map<String, Object> map2 = new HashMap<>();
        map2.put(clas, map1);
        Map<String, Object> map3 = new HashMap<>();
        map3.put(file, map2);

        //loop through repeating values to also add them to one value as you expected
        for (int j = jsonArray.length() - 1; j > i; j--) {
            JSONObject obj = getJsonChild(jsonArray.getJSONObject(j));

            String file1 = obj.getString("File");
            String clas1 = obj.getString("Class");
            String meth1 = obj.getString("Method");
            String anno1 = obj.getString("Annotation");

            if (file1.equals(file)) {
                if (map2.containsKey(clas1)) {
                    if (childrenContains(map2, meth1)) {
                        //if the difference was annotation value
                        map.put("Annotation", anno1);
                    } else {
                        //if the difference was method names
                        Map<String, String> map_ = new HashMap<>();
                        map_.put("Annotation", anno1);
                        ((Map<String, Object>) map2.get(clas1)).put(meth1, map_);
                    }
                } else {
                    //if the difference was class names
                    Map<String, String> map_ = new HashMap<>();
                    map_.put("Annotation", anno1);
                    Map<String, Object> map1_ = new HashMap<>();
                    map1_.put(meth1, map_);
                    map2.put(clas1, map1_);
                }

                //remove the (value added) object
                jsonArray.remove(j);
            }
        }

        //add the map to the result
        result.put(map3);
    }

    return  result.toString(4);
}

private static boolean childrenContains(Map<String, Object> map1, String meth1) {
    for (String childKey : map1.keySet()) {
        Map<String, Object> child = (Map<String, Object>) map1.get(childKey);
        if (child.containsKey(meth1))
            return true;
    }
    return false;
}

private static JSONObject getJsonChild(JSONObject object) throws JSONException {
    Iterator<String> keys = object.keys();
    String key = "";
    while (keys.hasNext()) {
        key = (String) keys.next();
    }
    return object.getJSONObject(key);
}

И результат для вашего образца с использованием моего кода: -

[
    {"file1.java": {"com.ETransitionActionType": {"values": {"Annotation": "Not Found"}}}},
    {"file2.java": {"com.ETransitionParams": {"values": {"Annotation": "Not Found"}}}},
    {"file3.java": {
        "com.ExecuteTransitionActionHandler": {
            "createBadRequestResponse": {"Annotation": "Not Found"},
            "extractParametersFromAction": {"Annotation": "Not Found"}
        },
        "com.phloc.commons.id.IHasID": {"getID": {"Annotation": "Not Found"}}
    }}
]

И если вы хотите получить данные json из файла, используйте следующую функцию, чтобы легко создать JSONArray: -

private static JSONArray readFromFile(String filePath){
    try {
        BufferedReader br = new BufferedReader(new FileReader(filePath));
        StringBuilder sb = new StringBuilder();
        String line = br.readLine();

        while (line != null) {
            sb.append(line);
            sb.append(System.lineSeparator());
            line = br.readLine();
        }
        return new JSONArray(sb.toString());
    } catch (Exception e) {
        System.out.println(e.getMessage());
        return null;
    }
}

И используйте вместо него текстовые данные json: -

...
//get the json array
jsonArray = readFromFile("FilePath");
...

Спасибо за Ваш ответ! Я пробую ваш код, но получаю сообщение об ошибке о том, что метод readFile не определен, следует ли импортировать что-нибудь для этого метода?

Sarah 18.10.2018 13:52

Извините, я использовал файл, который включает ваши данные json, я забыл удалить его после публикации ответа, теперь я отредактировал функцию.

Azhy 18.10.2018 13:54

Спасибо за ваш быстрый ответ. Было бы здорово, если бы вы предоставили мне эту функцию, которая считывает массив json из файла, поскольку у меня есть мой json в файле.

Sarah 18.10.2018 14:07

Хорошо, я покажу вам функцию readFile, но если сообщение устранило вашу проблему, вы можете нажать кнопку принятия, чтобы узнать, было ли это решением.

Azhy 18.10.2018 14:17

Другие вопросы по теме