question

neerajk22 avatar image
neerajk22 asked Erick Ramirez action

Getting error while de-serializing column with custom type using C# code

Getting error while de-serializing cassandra column with custom type using c# code

Cassandra sink connector (by lenses.io) is inserting data to one of the cassandra column of custom type - list<frozen<customType>>

Now when i am trying to read this column data it returns byte[] and when I am de-serializing same using Dot Net code then getting below error -

The input stream is not a valid binary format. The starting contents (in bytes) are: 43-53-52-30-30-30-30-30-30-30-32-31-00-00-00-0F-46 ...
MemoryStream memStream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter()
memStream.Write(arrBytes, 0, arrBytes.Length);
memStream.Seek(0, SeekOrigin.Begin);
object obj = (object)binForm.Deserialize(memStream); ----> This line is throwing error

"The input stream is not a valid binary format. The starting contents (in bytes) are: 43-53-52-30-30-30-30-30-30-30-32-31-00-00-00-0F-46 ..."

[UPDATED] Cassandra custom types used to create table -

create type additional_details(
    products list<frozen<product_details>>,
    retailers list<frozen<retailer>>
)
create type product_details(
    product_codes text,
    product_name text,
    product_classification text,
    quantity int
)
create type retailer(
    key text,
    value text
)

Cassandra table (initiation_table) is having one of the column with name "additiona_details" and below is the JSON which is inserted by Cassandra sink connector(by lenses.io) to this table.

FYI - Below data is avro formatted in topics and cassandra sink connector also configured to use avro formatted data and inserting data to cassandra table.

"additional_details": {
    "products": [
        {
            "product_codes": "product cd 1",
            "product_name": "prod test",
            "product_classification": "classa",
            "quantity": 1
        },
        {
            "product_codes": "product cd 2",
            "product_name": "prod testB",
            "product_classification": "ClassB",
            "quantity": 1
        }
    ],
    "retailers": [
        {
            "key": "key1",
            "value": "value
        }
    ]
}

Now when I am executing below line of code -

var rowSet = session.Execute("select additional_details from initiation_table");

"additional_details" is returned as byte[] from above query

var myAddDetailsbyteArr = row.GetValue<byte[]>("additional_details");
var testAdditionalObj = ByteArrayToObject(myAddDetailsbyteArr );

I am trying to convert above byte array to c# entity (as mentioned below) But getting error -

public class AdditionalDetails
{
    public ProductDetails[] products { get; set; }
    public KeyVal[] amendments { get; set; }
}

public class KeyVal
{
    public string key { get; set; }
    public string value { get; set; }
}

public class ProductDetails
{
    public string product_codes { get; set; }
    public string product_name { get; set; }
    public string product_classification { get; set; }
    public int quantity { get; set; }
}

// Method to return Addition detail object by converting byteArray to object.
public static object ByteArrayToObject(byte[] arrBytes)
{
    MemoryStream memStream = new MemoryStream();
    BinaryFormatter binForm = new BinaryFormatter();
    memStream.Write(arrBytes, 0, arrBytes.Length);
    memStream.Seek(0, SeekOrigin.Begin);
    AdditionalDetails obj = (AdditionalDetails)binForm.Deserialize(memStream); --> This line is throwing error
    return obj;
}
csharp driveruser-defined type
10 |1000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

1 Answer

Erick Ramirez avatar image
Erick Ramirez answered Erick Ramirez edited

In your app you need to map the UDT to an application entity. To do this, you need to create a C# class that maps to the user-defined type.

Here's an example UDT from the driver doc:

CREATE TYPE address (
   street text,
   city text,
   zip int,
   phones list<text>
)

And here's the class that maps to it:

public class Address
{
   public string Street { get; set; }
   public string City { get; set; }
   public int Zip { get; set; }
   public IEnumerable<string> Phones { get; set;}
}

For details, see the C# driver User-defined types doc page.

If you provide the table and UDT schema plus a minimal sample code, I'd be happy to get the Drivers engineers here at DataStax to have a look at it. Cheers!

[UPDATE] This question has been closed since the user has provided the repro steps in a new post #10394.

2 comments Share
10 |1000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

neerajk22 avatar image neerajk22 commented ·

Please check the details related to format and custom types used.

Shared in comment\answer section above.

0 Likes 0 ·
joao.reis avatar image joao.reis neerajk22 commented ·

Can you provide a code sample to show how you are using the driver to perform these operations? Ideally it would be a code sample that I could run on my machine to reproduce this behavior.

0 Likes 0 ·