[ 
https://issues.apache.org/jira/browse/AVRO-4054?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17880787#comment-17880787
 ] 

Zoltan Csizmadia edited comment on AVRO-4054 at 9/10/24 9:06 PM:
-----------------------------------------------------------------

If you create your own writer based on DefaultWriter, you can override the 
WriteMap call.

 
{code:java}
class MyDefaultWriter : DefaultWriter
{
    public MyDefaultWriter(Schema schema) : base(schema)
    {
    }

    protected override void WriteMap(MapSchema schema, object value, Encoder 
encoder)
    {
        var map = value as System.Collections.IDictionary;
        if (map == null)
        {
            throw new AvroTypeException("Map does not implement non-generic 
IDictionary");
        }
        encoder.WriteMapStart();
        encoder.SetItemCount(map.Count);
        foreach (System.Collections.DictionaryEntry de in map)
        {
            encoder.StartItem();
            encoder.WriteString(de.Key as string);
            Write(schema.ValueSchema, de.Value, encoder);
        }
        encoder.WriteMapEnd();
    }
} 

...

var schema = MapSchema.CreateMap(PrimitiveSchema.Create(Schema.Type.Long));
var ms = new MemoryStream();
BinaryEncoder enc = new BinaryEncoder(ms);
var writer = new MyDefaultWriter(schema);
writer.Write(new Dictionary<string, long>(), enc);
enc.Flush();{code}


was (Author: [email protected]):
If you create your own writer based on DefaultWriter, you can override the 
WriteMap call.

 
{code:java}
class MyDefaultWriter : DefaultWriter
{
    public MyDefaultWriter(Schema schema) : base(schema)
    {
    }

    protected override void WriteMap(MapSchema schema, object value, Encoder 
encoder)
    {
        var map = value as System.Collections.IDictionary;
        if (map == null)
        {
            throw new AvroTypeException("Map does not implement non-generic 
IDictionary");
        }        encoder.WriteMapStart();
        encoder.SetItemCount(map.Count);
        foreach (System.Collections.DictionaryEntry de in map)
        {
            encoder.StartItem();
            encoder.WriteString(de.Key as string);
            Write(schema.ValueSchema, de.Value, encoder);
        }
        encoder.WriteMapEnd();
    }
} 

...

var schema = MapSchema.CreateMap(PrimitiveSchema.Create(Schema.Type.Long));
var ms = new MemoryStream();
BinaryEncoder enc = new BinaryEncoder(ms);
var writer = new MyDefaultWriter(schema);
writer.Write(new Dictionary<string, long>(), enc);
enc.Flush();{code}

> Serialization of C# Dictionary only works if type is <string, object>
> ---------------------------------------------------------------------
>
>                 Key: AVRO-4054
>                 URL: https://issues.apache.org/jira/browse/AVRO-4054
>             Project: Apache Avro
>          Issue Type: Bug
>          Components: csharp
>    Affects Versions: 1.12.0
>         Environment: I was testing this in a .Net Standard 2.0 project.
>            Reporter: Rob Komjathy
>            Priority: Major
>
> I encountered an unexpected behavior with Avro Maps (C# Dictionaries).  If I 
> directly try to serialize a Dictionary<string, T> where T is any type besides 
> literally "object", an exception is thrown. 
> If you dig into the code, it's because you can't directly cast 
> Dictionary<string, T> to Dictionary<string, object>.  This fails on at least 
> 3 lines in DefaultWriter, as there are several attempts made to verify the 
> Dictionary "is" <string, object> or can be cast to it directly.
> For example, here is a rudimentary example.
>  
> {code:java}
> var schema = MapSchema.CreateMap(PrimitiveSchema.Create(Schema.Type.Long));
> var ms = new MemoryStream();
> Encoder enc = new BinaryEncoder(ms);
> var writer = new DefaultWriter(schema);
> writer.Write(new Dictionary<string, long>(), enc);
> enc.Flush(); {code}
> Given this example, I would expect to be able to pass a Dictionary<string, 
> long> given the schema I have defined.  Instead this throws an exception. 
>  
> The work around is to create a new Dictionary<string, object> and 
> individually cast the values to "objects".  For example:
>  
> {code:java}
> public static Dictionary<string, object> ToAvroSafeDictionary<TValue>(this 
> IDictionary<string, TValue> dictionary)
> {
>     return dictionary?.ToDictionary(k => k.Key, v => (object)v.Value);
> } {code}
> I originally encountered this with my own custom schema but as you can see, 
> using Apache Avro's own schema objects in the rudimentary example exhibit the 
> same issue.
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to