У меня есть следующий образец из файла 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();
}
Любые идеи? Ваша помощь очень ценится !!!




Вы можете создать карту карт для представления вашей группировки по «Файлу» и «Классу» для вашего списка (внутренних) объектов 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()));
}
}
См. Мой обновленный пример. Я считаю, что new FileReader("rawOutput.json") не возвращает исключений и находит нужный файл.
Спасибо за ваш быстрый ответ! Ваш код работает, но в нем есть ошибка, заключающаяся в том, что если в одном классе имеется более одного метода, он перечисляет только один метод внутри атрибута класса.
Я написал код, чтобы сделать то, что вам нужно, но сначала вы должны добавить эту библиотеку в свой проект, если у вас еще нет библиотека 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 не определен, следует ли импортировать что-нибудь для этого метода?
Извините, я использовал файл, который включает ваши данные json, я забыл удалить его после публикации ответа, теперь я отредактировал функцию.
Спасибо за ваш быстрый ответ. Было бы здорово, если бы вы предоставили мне эту функцию, которая считывает массив json из файла, поскольку у меня есть мой json в файле.
Хорошо, я покажу вам функцию readFile, но если сообщение устранило вашу проблему, вы можете нажать кнопку принятия, чтобы узнать, было ли это решением.
Большое спасибо за ответ! Не могли бы вы указать, как я могу использовать ваш метод с приведенным выше фрагментом кода? Как используется параметр "String json" в приведенном выше методе? а какой импорт вы использовали?