Skip to content

Commit

Permalink
AVRO-4075: Fix JsonDecoder string type failing to decode ISO string date
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanielAB committed Oct 8, 2024
1 parent 2ac5a46 commit 4574955
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
17 changes: 13 additions & 4 deletions lang/csharp/src/apache/main/IO/JsonDecoder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
Expand Down Expand Up @@ -45,6 +45,14 @@ private class ReorderBuffer
public JsonReader OrigParser { get; set; }
}

private class AvroJsonTextReader : JsonTextReader
{
public AvroJsonTextReader(TextReader reader) : base(reader)
{
this.DateParseHandling = DateParseHandling.None;
}
}

private JsonDecoder(Symbol root, Stream stream) : base(root)
{
Configure(stream);
Expand Down Expand Up @@ -85,7 +93,7 @@ public void Configure(Stream stream)
Parser.Reset();
reorderBuffers.Clear();
currentReorderBuffer = null;
reader = new JsonTextReader(new StreamReader(stream));
reader = new AvroJsonTextReader(new StreamReader(stream));
reader.Read();
}

Expand All @@ -100,7 +108,7 @@ public void Configure(string str)
Parser.Reset();
reorderBuffers.Clear();
currentReorderBuffer = null;
reader = new JsonTextReader(new StringReader(str));
reader = new AvroJsonTextReader(new StringReader(str));
reader.Read();
}

Expand Down Expand Up @@ -651,7 +659,7 @@ public override Symbol DoAction(Symbol input, Symbol top)
if (currentReorderBuffer != null && currentReorderBuffer.SavedFields.Count > 0)
{
throw TypeError("Unknown fields: " + currentReorderBuffer.SavedFields.Keys
.Aggregate((x, y) => x + ", " + y ));
.Aggregate((x, y) => x + ", " + y));
}

currentReorderBuffer = reorderBuffers.Pop();
Expand Down Expand Up @@ -735,6 +743,7 @@ private class JsonElementReader : JsonReader
public JsonElementReader(IList<JsonElement> elements)
{
this.elements = elements;
this.DateParseHandling = DateParseHandling.None;
pos = 0;
}

Expand Down
20 changes: 17 additions & 3 deletions lang/csharp/src/apache/test/IO/JsonCodecTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,20 @@ public void TestJsonDecoderNumeric(string type, object value)
}
}

[TestCase("{ \"s\": \"1900-01-01T00:00:00Z\" }", "1900-01-01T00:00:00Z")]
[TestCase("{ \"s\": \"1900-01-01T00:00:00.0000000Z\" }", "1900-01-01T00:00:00.0000000Z")]
[TestCase("{ \"s\": \"1900-01-01T00:00:00\" }", "1900-01-01T00:00:00")]
public void TestJsonDecoderStringDates(string json, string expected)
{
string def = "{\"type\":\"record\",\"name\":\"X\",\"fields\": [{\"type\": \"string\",\"name\":\"s\"}]}";
Schema schema = Schema.Parse(def);
DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema, schema);

var response = reader.Read(null, new JsonDecoder(schema, json));

Assert.AreEqual(expected, response["s"]);
}

// Ensure that even if the order of fields in JSON is different from the order in schema, it works.
[Test]
public void TestJsonDecoderReorderFields()
Expand Down Expand Up @@ -386,7 +400,7 @@ public partial class Root : global::Avro.Specific.ISpecificRecord
"o.Test\",\"fields\":[{\"name\":\"id\",\"type\":\"long\"}]}}},{\"name\":\"mymap\",\"default\":null," +
"\"type\":[\"null\",{\"type\":\"map\",\"values\":\"int\"}]}]}");
private IList<Avro.Test.Item> _myarray;
private IDictionary<string,System.Int32> _mymap;
private IDictionary<string, System.Int32> _mymap;

public virtual global::Avro.Schema Schema
{
Expand All @@ -399,7 +413,7 @@ public IList<Avro.Test.Item> myarray
set { this._myarray = value; }
}

public IDictionary<string,System.Int32> mymap
public IDictionary<string, System.Int32> mymap
{
get { return this._mymap; }
set { this._mymap = value; }
Expand All @@ -423,7 +437,7 @@ public virtual void Put(int fieldPos, object fieldValue)
this.myarray = (IList<Avro.Test.Item>)fieldValue;
break;
case 1:
this.mymap = (IDictionary<string,System.Int32>)fieldValue;
this.mymap = (IDictionary<string, System.Int32>)fieldValue;
break;
default: throw new global::Avro.AvroRuntimeException("Bad index " + fieldPos + " in Put()");
}
Expand Down

0 comments on commit 4574955

Please sign in to comment.