Uploaded image for project: 'Apache Avro'
  1. Apache Avro
  2. AVRO-1664

PHP library can't serialise records with optional (union-null) values

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 1.7.7
    • 1.10.0
    • php
    • None
    • php 5.5.15 OS X 10.9

    Description

      PHP avro serialising doesn't appear to support "optional" fields in records.

      Consider the PHP script below:

      <?php
      
      require_once('lib/avro.php');
      
      $schema_json = <<<_JSON
      {"name":"member",
       "type":"record",
       "fields":[{"name":"one", "type":"int"},
                 {"name":"two", "type":["null", "string"]}
                 ]}
      _JSON;
      
      $schema = AvroSchema::parse($schema_json);
      
      // Our datum is missing the 'optional' field (i.e. it's null)
      $datum = array("one" => 1);
      
      $io = new AvroStringIO();
      $writer = new AvroIODatumWriter($schema);
      $encoder = new AvroIOBinaryEncoder($io);
      $writer->write($datum, $encoder);
      $bin = $io->string();
      
      echo bin2hex($bin) . "\n";
      

      My understanding from documentation is that this should work and output the encoded binary in hex.

      Instead it throws:

      PHP Fatal error:  Uncaught exception 'AvroIOTypeException' with message 'The datum array (
        'one' => 1,
      ) is not an example of schema {"type":"record","name":"member","fields":[{"name":"one","type":"int"},{"name":"two","type":["null","string"]}]}'
      

      It's possible that this is not a valid usage of Avro and I'm mistaken in my expectations, so I tried the python library as a comparison. Sure enough the following script works as expected:

      from avro import schema
      from avro import io
      from StringIO import StringIO
      
      s = schema.parse("""
          {"name":"member",
          "type":"record",
          "fields":[{"name":"one", "type":"int"},
                    {"name":"two", "type":["null", "string"]}
                   ]}""")
      
      writer = StringIO()
      encoder = io.BinaryEncoder(writer)
      datum_writer = io.DatumWriter(s)
      datum_writer.write({"one": 1}, encoder)
      
      print writer.getvalue().encode("hex")
      

      which outputs:

      $ python avro_test.py
      0200
      

      As expected.

      Attachments

        Activity

          People

            siad007 Siad Ardroumli
            banks Paul Banks
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: