My part of the task is:
I need to collect productId
-s into list from two JSON
files with different data and pass it into the custom method with directory
of JSON
files.
I have two JSON
files with different data as the following:
And my code
is in the next format:
public class Main {
public static void main(String[] args) throws IOException, ParseException {
JSONParser parser = new JSONParser();
InputStream isOne = JSONParser.class.getResourceAsStream("/test/java/resources/json/file/product_0001690510.json");
InputStream isTwo = JSONParser.class.getResourceAsStream("/test/java/resources/json/file/product_0001694109.json");
// ... need to use somehow InpuStream for reading two JSON files with different structure inside
JSONArray arr = obj.getJSONArray("products"); // notice that `"products": [...]`
String productId = null;
for (int i = 0; i < arr.length(); i ) {
productId = arr.getJSONObject(i).getString("productID");
}
List<String> productIds = new ArrayList<>(Collections.singleton(productId));
for (var file : obj.keySet()) {
System.out.println(getAllExportsWithProductIds(file, productIds));
}
}
public static List<String> getAllExportsWithProductIds(String directory, List<String> productIds) throws IOException {
var matchingObjects = new ArrayList<String>();
try (var fileStream = Files.walk(Path.of(directory))) {
for (var file : fileStream.toList()) {
var json = Json.readString(Files.readString(file));
var objects = JsonDecoder.array(json);
for (var object : objects) {
var objectProductIDs = JsonDecoder.field(
object, "products",
JsonDecoder.array(JsonDecoder.field("productID", JsonDecoder::string))
);
for (var productId : objectProductIDs) {
if (productIds.contains(productId)) {
matchingObjects.add(Json.writeString(object));
break;
}
}
}
}
}
return matchingObjects;
}
}
Based on it my question is:
Can I read all provided JSON
files at the same time to collect productId
-s into list? If yes, how can I do that if I have the different data of two JSON
files.
To clarify a bit:
"By different data, I mean, in general, the
number
of these fields (for example,productId
fields in both ofJSON
-s: №1 and №2 accordingly), their order. That is, how an array object differs from another.If these
JSON
-s have the same data, it'd be easier to parse, but in this specific usecase I need to find the way how to handle both of them in different way as their data is not in the same format of representation."
My detailed explanation how I see it in abstract way:
How I see it abstractly in the lifecycle of developing.
I've already read different articles and checked libraries as:
and so on,
but I'm still struggling with understanding how to apply it correctly, for this reason, I'm looking for a concrete solution.
Thank you in advance for any smart and helpful ideas. If you need some additional details, I'm ready to provide without any problem.
UPD:
There's I have another version of code, which is collecting productID
-s, I need just to find the way how to combine with the first version of code and that's it:
public class ProductIdImporter {
public ProductIdImporter() {
// TODO Auto-generated constructor stub
}
public void importJson() {
List<Path> paths = Arrays.asList(Paths.get("C:\\Users\\pc\\IdeaProjects\\jsonapi\\src\\test\\java\\resources\\json\\product_0001690510.json"),
Paths.get("C:\\Users\\pc\\IdeaProjects\\jsonapi\\src\\test\\java\\resources\\json\\product_0001694109.json"));
ObjectMapper jsonMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Set<String> productIds = paths.stream().map(path -> {
try {
return jsonMapper.readValue(Files.newInputStream(path), ExportList[].class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}).map(Arrays::asList)
.flatMap(List::stream)
.map(ExportList::productList)
.flatMap(List::stream)
.map(Product::getId)
.collect(Collectors.toSet());
productIds.forEach(System.out::println);
}
public static void main(String[] args) {
ProductIdImporter importer = new ProductIdImporter();
importer.importJson();
}
static class ExportList {
public List<Product> products;
public ExportList() {
}
public List<Product> productList() {
return products;
}
}
static class Product {
public String productID;
public Product() {
}
public String getId() {
return productID;
}
}
}
CodePudding user response:
Taking the JSON №1 you have included in your post basically it is an array of json objects with the same format like below (I have included just the first one element and deleted all the properties you are not interested to parse):
[{
"products": [
{
"colorWayID": "IMP5002620012114",
"productID": "0001755256"
},
{
"colorWayID": "IMP8473190012114",
"productID": "0001690510"
},
{
"colorWayID": "IMP9100570012114",
"productID": "0001700877"
}
],
...other properties excluded from parsing
}]
To iterate over this array you can read your json file into a ArrayNode
and iterate over every element:
ArrayNode arrayNode = (ArrayNode) mapper.readTree(json);
for (int i = 0; i < arrayNode.size(); i) {/*inspecting products property*/}
The products property is an array of JsonNode
containing the productID property you want to extract, you can use the JsonNode#get
method to extract both the products and productID properties:
List<String> productIds = new ArrayList<>();
ArrayNode arrayNode = (ArrayNode) mapper.readTree(json);
for (int i = 0; i < arrayNode.size(); i) {
//products property is also an array
ArrayNode products =(ArrayNode) arrayNode.get(i).get("products");
for (int j = 0; j < products.size(); j) {
//adding productId to your list
productIds.add(products.get(j).get("productID").asText());
}
}
This process can be repeated for other json files with variations depending from the json structure contained in them, but substantially it remains the same.