简体   繁体   中英

How to add wrapper JSON to Mutiny Multi?

I have a Java method which creates the customer information in JSON format using the streams approach and returns as and when it is created in an asynchronous approach using the Multi from SmallRye Mutiny .

I would like to add the wrapper to this JSON which is being created using the Jackson JsonGenerator . I don't understand how to add the same. I believe I need to make use of the Multi.createBy().concatenating() to achieve this .

The following is the method that I have:

public static Multi<Customer> generateCustomer(final Input input) {
    try {
        return Multi.createFrom().publisher(new CustomerPublisher(input));
    } catch (Exception e) {
        throw new NewException("Exception occurred during the generation of Customer : " + e);
    }
}

The above method currently returns something like this asynchronously:

[
  {
    "name":"Batman",
    "age":45,
    "city":"gotham"
  },
  {
    "name":"superman",
    "age":50,
    "city":"moon"
  }
]

I would like to add a wrapper to this JSON and create something like this:

{
  "isA": "customerDocument",
  "createdOn": "2022-10-10T12:29:43",
  "customerBody": {
    "customerList": [
      {
        "name": "Batman",
        "age": 45,
        "city": "gotham"
      },
      {
        "name": "superman",
        "age": 50,
        "city": "moon"
      }
    ]
  }
}

So I have added a method which does this and I would like to call the same, but I am unable to append the same to my return Multi.createFrom().publisher

public class CustomerGenerator {

    private ByteArrayOutputStream jsonOutput;
    private JsonGenerator jsonGenerator;

    private CustomerGenerator() {
        try {
            jsonOutput = new ByteArrayOutputStream();
            jsonGenerator = new JsonFactory().createGenerator(jsonOutput).useDefaultPrettyPrinter();
        } catch (IOException ex) {
            throw new TestDataGeneratorException("Exception occurred during the generation of customer document : " + ex);
        }
    }

    public static Multi < Customer > generateCustomer(final Input input) {
        CustomerGenerator customerGenerator = new CustomerGenerator();
        customerGenerator.wrapperStart();
        try {
            return Multi.createFrom().publisher(new CustomerPublisher(input));
        } catch (Exception e) {
            throw new NewException("Exception occurred during the generation of Customer : " + e);
        } finally {
            System.out.println("ALL DONE");
            customerGenerator.wrapperEnd();
        }
    }

    public void wrapperStart() {
        try {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("type", "customerDocument");
            jsonGenerator.writeStringField("creationDate", Instant.now().toString());
            jsonGenerator.writeFieldName("customerBody");
            jsonGenerator.writeStartObject();
            jsonGenerator.writeFieldName("customerList");
        } catch (IOException ex) {
            throw new TestDataGeneratorException("Exception occurred during customer document wrapper creation : " + ex);
        }
    }

    public void wrapperEnd() {
        try {
            jsonGenerator.writeEndObject(); // End body
            jsonGenerator.writeEndObject(); // End whole json file
        } catch (IOException ex) {
            throw new TestDataGeneratorException("Exception occurred during customer document wrapper creation : " + ex);
        } finally {
            try {
                jsonGenerator.close();
                System.out.println("JSON DOCUMENT STRING : " + jsonOutput.toString());
            } catch (Exception e) {
                // do nothing
            }
        }
    }

}

Your approach wouldn't make as you are wrapping random input that goes out of the CustomGenerator control.

Since you are able to generate the final output only when all emitted Customer object are emitted, and supposing you would like to retain a object oriented approach (ie not shifting to emitting JSON tokens), you should collect the emitted customers then wrap the collected items into your final JSON output:

Uni<byte[]> result = Multi.createFrom().publisher(new CustomerPublisher(input))
    .collect()
    .asList()
    .map(customers -> {
        ByteArrayOutputStream jsonOutput = new ByteArrayOutputStream();
        JsonGenerator jsonGenerator = new JsonFactory().createGenerator(jsonOutput).useDefaultPrettyPrinter();
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("type", "customerDocument");
        jsonGenerator.writeStringField("creationDate", Instant.now().toString());
        jsonGenerator.writeFieldName("customerBody");
        jsonGenerator.writeStartObject();
        jsonGenerator.writeArrayFieldStart("customerList");
        customers.forEach(customer -> jsonGenerator.writeObject(customer));
        jsonGenerator.writeEndArray();
        jsonGenerator.writeEndObject();
        jsonGenerator.writeEndObject();
        jsonGnenerator.close();
        return jsonOutput.toByteArray();
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM