jackson-dataformats-binary icon indicating copy to clipboard operation
jackson-dataformats-binary copied to clipboard

Caused by: com.fasterxml.jackson.core.JsonParseException: Invalid length indicator for String: -98

Open birTiwana opened this issue 1 year ago • 2 comments

I have created a very simple avro schema file:

{
   "name":"SampleRecordDto",
   "type":"record",
   "namespace":"com.api.jsonata4java.avro.v1",
   "fields":[
      {
         "name":"name",
         "type":"string"
      }
   ]
}

Then generating a SampleRecordDto file from this using the following avro-maven-plugin.


			<plugin>
				<groupId>org.apache.avro</groupId>
				<artifactId>avro-maven-plugin</artifactId>
				<version>1.8.2</version>
				<executions>
					<execution>
						<phase>generate-sources</phase>
						<goals>
							<goal>schema</goal>
						</goals>
						<configuration>
							<sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory>
							<outputDirectory>${project.build.directory}/generated-sources/avro/</outputDirectory>
						</configuration>
					</execution>
				</executions>
			</plugin>

After then using jackson-dataformat-avro to convert an object of class SampleRecodDto to JSONNode using the following code:

package com.api.jsonata4java.test.expressions;

import com.api.jsonata4java.avro.v1.SampleRecordDto;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.dataformat.avro.AvroMapper;
import com.fasterxml.jackson.dataformat.avro.AvroSchema;
import org.apache.avro.Schema;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;

public class AvroTest {
    private static final AvroMapper avroMapper = new AvroMapper();
    public static void main(String[] args) throws IOException {
        SampleRecordDto sampleRecordDto = SampleRecordDto.newBuilder()
                .setName("apm")
                .build();

        JsonNode jsonNode = decode(sampleRecordDto.getSchema(), sampleRecordDto.toByteBuffer().array());
        System.out.println(jsonNode);

    }

    public  static JsonNode decode(Schema schema, byte[] message) {
        try (InputStream input = new ByteArrayInputStream(message)) {
            return avroMapper.reader(new AvroSchema(schema)).readTree(input);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }
}

But I am running into the following exception:

Exception in thread "main" java.io.UncheckedIOException: com.fasterxml.jackson.core.JsonParseException: Invalid length indicator for String: -98
	at com.api.jsonata4java.test.expressions.AvroTest.decode(AvroTest.java:31)
	at com.api.jsonata4java.test.expressions.AvroTest.main(AvroTest.java:22)
Caused by: com.fasterxml.jackson.core.JsonParseException: Invalid length indicator for String: -98
	at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2418)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:749)
	at com.fasterxml.jackson.dataformat.avro.deser.JacksonAvroParserImpl.decodeString(JacksonAvroParserImpl.java:574)
	at com.fasterxml.jackson.dataformat.avro.deser.JacksonAvroParserImpl.decodeStringToken(JacksonAvroParserImpl.java:565)
	at com.fasterxml.jackson.dataformat.avro.deser.ScalarDecoder$StringReader$FR.readValue(ScalarDecoder.java:317)
	at com.fasterxml.jackson.dataformat.avro.deser.RecordReader$Std.nextToken(RecordReader.java:142)
	at com.fasterxml.jackson.dataformat.avro.deser.AvroParserImpl.nextToken(AvroParserImpl.java:97)
	at com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer._deserializeContainerNoRecursion(JsonNodeDeserializer.java:539)
	at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:98)
	at com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer.deserialize(JsonNodeDeserializer.java:23)
	at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323)
	at com.fasterxml.jackson.databind.ObjectReader._bindAsTree(ObjectReader.java:2149)
	at com.fasterxml.jackson.databind.ObjectReader._bindAndCloseAsTree(ObjectReader.java:2117)
	at com.fasterxml.jackson.databind.ObjectReader.readTree(ObjectReader.java:1794)
	at com.api.jsonata4java.test.expressions.AvroTest.decode(AvroTest.java:29)

Can I please get some help on this?

birTiwana avatar Nov 15 '22 05:11 birTiwana

One thing to check, I think, is to ensure that this:

sampleRecordDto.toByteBuffer().array()

returns valid encoded document where content is at 0-offset. ByteBuffer could return backing array that has different offset; so checking what ByteBuffer.arrayOffset() returns would be good -- if it's not 0 there'd be a problem. In general there is some discrepancy between data being decoded and schema; Avro as a format is very fragile unfortunately (as it thrives to be as compact as possible, little redundancy) and it is very easy to get corrupt data.

Also make sure to use a recent Jackson version; I don't think that is necessarily the problem here but sometimes bugs are reported against very old version and fix exists in newer versions.

cowtowncoder avatar Nov 15 '22 22:11 cowtowncoder

I checked and the value ByteBuffer.arrayOffset() is actually 0.

birTiwana avatar Nov 15 '22 22:11 birTiwana