2

If both the producer and consumer of events/messages are .Net/C# based, I tend to use metadata in the payload in order to be able to deserialised the data into C# POCOs like so:

Data
{
  "X": {
    "a": "bb811ea5-6993-e511-80fc-1458d043a750",
    "b": "ddd",
    "b": "dddd",
    "d": true
  }
  "x1": 1.1234,
  "x2": 2.3456,
  "EventUtcDateTime": "2016-02-16T08:55:38.5103574Z"
}

Metadata
{
  "TimeStamp": "02/16/2016 08:55:37",
  "EventClrTypeName": "Bla.Di.Bla.SomeClass, Bla.Di.Bla, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
}

What would be a good solution in situations where the producer is not .Net/C# based?

mat-mcloughlin
  • 6,492
  • 12
  • 45
  • 62
cs0815
  • 16,751
  • 45
  • 136
  • 299
  • Why not just go for a standard JSON or XML style, all languages have good libraries to manage such formats? – Ouarzy Feb 16 '16 at 10:22
  • I know but how do you know how to deserialize it if you have no meta data? – cs0815 Feb 16 '16 at 10:39
  • Maybe I miss something, you mean you don't even know the type your suppose to read? Usually you have a POCO type corresponding to the object you want to read, as explain here no? http://stackoverflow.com/questions/10350982/deserialize-json-string-to-c-sharp-object – Ouarzy Feb 16 '16 at 10:44
  • Yes of course. However, the producer may create 'objects'/json data for which I did not have a poco yet. i also need to know from the json which poco to use if there is already one to hydrate the poco. – cs0815 Feb 16 '16 at 11:37
  • Ah ok, yes you need something like JsonConvert.DeserializeObject(json, Type.GetType(@event.Event.EventType))... For me a logical answer would be add a mandatory EventType in any JSON events shared by different context. – Ouarzy Feb 16 '16 at 13:34
  • Thanks so EventType should be a mandatory part of the Data rather than the Metadata. Fell free to create an answer. – cs0815 Feb 17 '16 at 13:03

2 Answers2

7

The EventData class contains a property Properties... that allow you to add metadata to the message:

Gets the user properties of the event data that the user explicitly added during send operations.

So to send a event :

var eventHubClient = EventHubClient.CreateFromConnectionString("connectionString", "eventHubName");
var mypoco = new POCO();
// ...

// Get the Json string
var stringBody = JsonConvert.SerializeObject(mypoco);

// Create the event data
var eventData = new EventData(Encoding.UTF8.GetBytes(stringBody));

// Add the event type.
eventData.Properties.Add("EventType", typeof(POCO).Assembly.FullName);

// Send the data.
eventHubClient.Send(eventData);

While receiving your message, you'll get the event type from the metada of the message:

async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
    foreach (EventData eventData in messages)
    {
        var jsonBody = Encoding.UTF8.GetString(eventData.GetBytes());

        //Get the event type
        var eventTypeName = (string)eventData.Properties["EventType"];
        var eventType = Type.GetType(eventTypeName);

        // Deserialize the object
        var myPoco = JsonConvert.DeserializeObject(jsonBody, eventType);
    }
}

Otherwise you can get rid of the body type by using a JObject

async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
    foreach (EventData eventData in messages)
    {
        var jsonBody = Encoding.UTF8.GetString(eventData.GetBytes());

        // Deserialize the json as a JObject
        var myPoco = JObject.Parse(jsonBody);
        var a = myPoco["X"]["a"];

    }
}
Thomas
  • 24,234
  • 6
  • 81
  • 125
2

For me a logical answer would be add a mandatory EventType in any JSON events shared by different context.

Thus EventType should be a mandatory part of the Data rather than the Metadata.

Ouarzy
  • 3,015
  • 1
  • 16
  • 19