0

What I need:

I need to get String representation of two JSON files separately or at the same time, if it possible.

To send it to the method with declaration as:

public static List<String> getAllExportsWithProductIds(String directory, List<String> productIds)

What I have:

I'm working with the following version of code as:

public class ProductIdImporter {
    public ProductIdImporter() {
        // TODO Auto-generated constructor stub
    }

    public void importJson() throws IOException {
        //List<String> stringList = Arrays.asList("0001755256", "0001694109");
        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);

        List<String> productIds = paths
                .stream()
                .map(path -> {
                    try {
                        return jsonMapper
                                .readValue(Files.newInputStream(path), Product[].class);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }).map(Arrays::asList)
                .flatMap(List::stream)
                .map(Product::getId)
                .toList();
        productIds.forEach(System.out::println);

        try {
            String content = new String(Files.readAllBytes(Paths.get("C:\\Users\\pc\\IdeaProjects\\jsonapi\\src\\test\\java\\resources\\json\\product_0001690510.json",
                    "C:\\Users\\pc\\IdeaProjects\\jsonapi\\src\\test\\java\\resources\\json\\product_0001694109.json")), StandardCharsets.UTF_8);
            // default StandardCharsets.UTF_8
            System.out.println(getAllExportsWithProductIds(content, productIds));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        ProductIdImporter importer = new ProductIdImporter();
        importer.importJson();
    }

    static class ExportList {
        public List<Product> products;

        public ExportList() {
        }

        public List<Product> getProducts() {
            return products;
        }
    }

    static class Product {
        public String productID;

        public Product() {
        }

        public String getId() {
            return productID;
        }
    }

    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;
                        }
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return matchingObjects;
    }
}

where I need to get the access specifically to the directory to read two JSON files separately to get as a parameter String representation each of them to send to the custom method for handling based on productID parameter:

  1. JSON №1
  2. JSON №2

The directory is: C:\Users\pc\IdeaProjects\jsonapi\src\test\java\resources\json

before handling list of id-s.

My project-structure of the project is as in the buttom provided:

C:.
├───.idea
│   ├───artifacts
│   ├───inspectionProfiles
│   └───libraries
├───out
│   └───artifacts
│       └───jsonapi_jar
├───src
│   ├───main
│   │   ├───java
│   │   │   └───org.example
│   │   └───resources
│   │       └───META-INF
│   └───test
│       └───java
│           └───resources
│               └───json
└───target
    ├───classes
    │   ├───META-INF
    │   └───org
    │       └───example
    └───generated-sources
        └───annotations

What I tried:

№1: I have updated my code version. I need to get the access to the directory with JSON-s correctly

№2: I have updated again with newer version, but still no luck.

№3: I have tried to use the code snippet based on this answer, but it returns me still the error while reading and parsing it as InvalidPathException.java.


While running the attached code and reading the content inside JSON-s, I'm reproducing the issue as:

Exception in thread "main" java.nio.file.InvalidPathException: Illegal char <:> at index

in one of my provided attempts.


To summarize:

As you can see, I'm passing a directory to the method instead of a file and that doesn't work.

Based on it, my question is:

How can I do each file at a time and manage them after? If it doesn't make sense to try to do two at the same time. Can I handle two files of JSON-s as one file at a time, parse to String, and send each of them to the method for handling? Is it possible, at all?

Thank you in advance for your ideas how to handle it. If you need more details, I'm ready to provide.

invzbl3
  • 5,872
  • 9
  • 36
  • 76
  • The code you show does something completely different from the question that you claim you have. Hence it is not clear what your question exactly is. Do you have problems accessing the directory, reading the files, getting the contents of a file into a string, parsing that string as a json object? What is your problem? – fishinear Feb 05 '23 at 13:20
  • @fishinear, I disagree with the statement about "completely different". In my code I've specified `String content` with `strings` of locations to `JSON`-s. I need to read both of `JSON`-s and then get as a `String` representation the parameter to pass it in the provided custom method as `getAllExportsWithProductIds`. The problem is I can't do it in the way which I attached in the example. – invzbl3 Feb 05 '23 at 13:27
  • That does not clarify what your problem is. Do you have problems accessing the directory, reading the files, getting the contents of a file into a string, parsing that string as a json object? What is your problem? – fishinear Feb 05 '23 at 13:29
  • The problem is how to read two `JSON`-s with the content inside to get `String` representation for both of them to pass it to the custom method. I've received the requirement to send two `JSON`-s somehow as a `String` representation to the custom method. I don't quite understand the way how can I do that correctly. I can improve the question, if it helps to clarify it. – invzbl3 Feb 05 '23 at 13:32
  • 1
    See https://stackoverflow.com/q/14169661/908621 for how to read the full contents of a file into a String. – fishinear Feb 05 '23 at 13:35
  • @fishinear, thank you for the example. I'm investigating it now. – invzbl3 Feb 05 '23 at 13:38
  • @fishinear, I've just checked your provided [example](https://stackoverflow.com/q/14169661/908621) and [it doesn't for me](https://gist.github.com/invzbl3/e81f1a71bb8dcffa42e59a29adf69f7a#file-productidimporter-java-L44). It's working by the same principle as I did in the [second attempt](https://gist.github.com/invzbl3/49c8b9df28fda1ea973b799596db3487#file-productidimporter2-java-L45). I'm getting the issue related to [indexes](https://gist.github.com/invzbl3/a8abb5a50ca6c44519b67c5d5e4b9299#file-invalidpathexception-java-L30), but thank you a lot for your effort to help me with it. – invzbl3 Feb 05 '23 at 14:00
  • 1
    You might want to update your question, so that it clearly states what you want to achieve, what you have tried and what problem you run into. Remove anything not related to the problem. For example, as I understand your problem, it has nothing to do with the fact the files contain JSON . So remove that from the problem definition. – fishinear Feb 05 '23 at 14:06
  • @fishinear, no problem, I've updated the question with concrete error and the way I'm using for reproducing it. Hope it makes more sense now. – invzbl3 Feb 05 '23 at 14:14
  • 1
    The "invalid path exception" tells you exactly what the problem is: you are using a file path that is invalid on your computer. It even tells you which character is invalid. – fishinear Feb 05 '23 at 14:19

1 Answers1

0

As one of ways it could be implemented as provided below:

public class ProductIdImporter {
    record ExportList(Json undecoded, List<Product> products) {
        static ExportList fromJson(Json json) {
            return new ExportList(
                    json,
                    JsonDecoder.field(json, "products", JsonDecoder.array(Product::fromJson))
            );
        }
    }

    record Product(String productID) {
        static Product fromJson(Json json) {
            return new Product(JsonDecoder.field(
                    json,
                    "productID",
                    JsonDecoder::string
            ));
        }
    }

    public static List<ExportList> loadExports(InputStream resource) throws IOException {
        var json = Json.read(new InputStreamReader(resource));
        return JsonDecoder.array(json, ExportList::fromJson);
    }

    public static List<Json> getAllExportsWithProductIds(List<String> resources, List<String> productIds) throws IOException {
        var exports = new ArrayList<ExportList>();
        for (var resource : resources) {
            try (var inputStream = Objects.requireNonNull(ProductIdImporter.class.getResourceAsStream(resource))) {
                exports.addAll(loadExports(inputStream));
            }
        }

        return  exports.stream()
                .filter(export -> export.products
                        .stream()
                        .anyMatch(product -> productIds.contains(product.productID))
                )
                .map(ExportList::undecoded)
                .toList();

    }

    public static void main(String[] args) throws IOException {
        var resources = List.of("/product1.json", "/product2.json");
        var productIds = List.of( "00017552897");
        System.out.println(getAllExportsWithProductIds(
                resources,
                productIds
        ));
    }
}
invzbl3
  • 5,872
  • 9
  • 36
  • 76