Bringing together the Apache Cassandra experts from the community and DataStax.

Want to learn? Have a question? Want to share your expertise? You are in the right place!

Not sure where to begin? Getting Started

 

question

neerajk22 avatar image
neerajk22 asked ·

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 characters needed characters left characters exceeded

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 ·

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 characters needed characters left characters exceeded

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

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

Shared in comment\answer section above.

0 Likes 0 ·

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 ·