content: package tech.allegro.schema.json2avro.converter;
  
  import org.apache.avro.Conversion;
  import org.apache.avro.Schema;
  import org.apache.avro.generic.GenericData;
  import org.apache.avro.generic.GenericDatumReader;
  import org.apache.avro.generic.GenericDatumWriter;
  import org.apache.avro.generic.GenericRecord;
  import org.apache.avro.io.BinaryDecoder;
  import org.apache.avro.io.DatumWriter;
  import org.apache.avro.io.DecoderFactory;
  import org.apache.avro.io.NoWrappingJsonEncoder;
  import org.apache.avro.specific.SpecificData;
  import org.apache.avro.specific.SpecificDatumWriter;
  import org.apache.avro.specific.SpecificRecord;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.util.Arrays;
  
  public class AvroJsonConverter {
      private final SpecificData specificData;
      private final GenericData genericData;
  
      public AvroJsonConverter(Conversion<?>... conversions) {
          specificData = new SpecificData();
          genericData = new GenericData();
          Arrays.stream(conversions).forEach(it -> {
                      specificData.addLogicalTypeConversion(it);
                      genericData.addLogicalTypeConversion(it);
                  }
          );
      }
  
      public byte[] convertToJson(byte[] avro, String schema) {
          return convertToJson(avro, new Schema.Parser().parse(schema));
      }
  
      public byte[] convertToJson(byte[] avro, Schema schema) {
          try {
              BinaryDecoder binaryDecoder = DecoderFactory.get().binaryDecoder(avro, null);
              GenericRecord record = new GenericDatumReader<GenericRecord>(schema, schema, genericData).read(null, binaryDecoder);
              return convertToJson(record);
          } catch (IOException e) {
              throw new AvroConversionException("Failed to create avro structure.", e);
          }
      }
  
      public byte[] convertToJson(GenericRecord record) {
          try {
              ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
              NoWrappingJsonEncoder jsonEncoder = new NoWrappingJsonEncoder(record.getSchema(), outputStream);
              DatumWriter<GenericRecord> writer = record instanceof SpecificRecord ?
                      new SpecificDatumWriter<>(record.getSchema(), specificData) :
                      new GenericDatumWriter<>(record.getSchema(), genericData);
              writer.write(record, jsonEncoder);
              jsonEncoder.flush();
              return outputStream.toByteArray();
          } catch (IOException e) {
              throw new AvroConversionException("Failed to convert to JSON.", e);
          }
      }
  }