Deserializing IEnumerable properties

584 views
Skip to first unread message

Thomas

unread,
Dec 23, 2014, 3:50:13 AM12/23/14
to masstrans...@googlegroups.com
I have troubles consuming messages that contain IEnumerable properties.

The following error is recorded by JSON deserializer while retrieving a message from the queue:

MassTransit.Transports.Endpoint [Unrecognized message loopback://localhost/queue:e0170000-6eea-80c1-a100-08d1ec9d3485]
System.Runtime.Serialization.SerializationException: Failed to deserialize the message ---> Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[ComTrade.Travel.MyWay.MyWayAppTest.External.MassTransitIssuesTests+SomeClass]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

I haven't found anything similar being noticed yet by anyone, so I guess I must be doing something wrong. Could you please point me in the right direction?
If I change the message contract to use generic List instead of an IEnumerable, the deserialization works as expected. However, I don't want to be forced to change the entire domain model just to enable passing it through the message queue.


Here is the entire sample code to reproduce the problem:

    /// <summary>
   
/// The mass transit issues tests.
   
/// </summary>
   
[TestFixture]
   
public class MassTransitIssuesTests
   
{
       
/// <summary>
       
/// Test the serialization of a property containing an enumerable list.
       
/// </summary>
       
[Test]
       
public void DeserializeEnumerables()
       
{
           
var bus = ServiceBusFactory.New(sbc =>
           
{
                sbc
.ReceiveFrom("loopback://localhost/queue");
                sbc
.UseLog4Net();
                sbc
.Subscribe(subs =>
               
{
                    subs
.Handler<TestRequest>((cxt, msg) =>
                   
{
                        cxt
.Respond(new TestResponse { Text = "RESP" + msg.Text });
                   
});
               
});
           
});

           
Assert.IsNotNull(bus);

           
try
           
{
                bus
.PublishRequest(
                   
new TestRequest { Text = "whatever", ListOfSomeClasses = new List<SomeClass>(new[] { new SomeClass { Value = "Some value" }, }) },
                    x
=>
                       
{
                            x
.Handle<TestResponse>(message => Console.WriteLine(message.Text));
                            x
.SetTimeout(new TimeSpan(0, 0, 10));
                       
});
           
}
           
catch (Exception ex)
           
{
               
Console.WriteLine(ex.Message);
           
}
           
finally
           
{
                bus
.Dispose();
           
}            
       
}

       
/// <summary>
       
/// Basic test request message.
       
/// </summary>
       
public class TestRequest
       
{
           
/// <summary>
           
/// Gets or sets the text.
           
/// </summary>
           
public string Text { get; set; }

           
/// <summary>
           
/// Gets or sets the list of some classes.
           
/// </summary>
           
public IEnumerable<SomeClass> ListOfSomeClasses { get; set; }
       
}

       
/// <summary>
       
/// Basic test response message.
       
/// </summary>
       
public class TestResponse
       
{
           
/// <summary>
           
/// Gets or sets the text.
           
/// </summary>
           
public string Text { get; set; }
       
}

       
/// <summary>
       
/// The some class.
       
/// </summary>
       
public class SomeClass
       
{
           
/// <summary>
           
/// Gets or sets the value.
           
/// </summary>
           
public string Value { get; set; }
       
}
   
}



Thanks in advance!

Regards,
Thomas

Chris Patterson

unread,
Dec 23, 2014, 11:53:57 AM12/23/14
to masstrans...@googlegroups.com
Use an array (SomeClass[]) or IList<SomeClass>, as it serializes better. I would recommend array.

--
You received this message because you are subscribed to the Google Groups "masstransit-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to masstransit-dis...@googlegroups.com.
To post to this group, send email to masstrans...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/masstransit-discuss/b43d839d-57f7-42c6-a0f1-2bd278dcd71e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Thomas

unread,
Dec 24, 2014, 3:22:05 AM12/24/14
to masstrans...@googlegroups.com
Thanks, yes, like I said - I already tried that and it solves the problem, but I was hoping I won't be forced to replace all my IEnumerable definitions throughout the model just to be able to pass it through the queue. I was hoping there was another workaround.


Chris Patterson

unread,
Dec 24, 2014, 3:03:46 PM12/24/14
to masstrans...@googlegroups.com
It should be a fairly easy addition to the serialization converter in the Json code, I'll try to take a look today as I'm going through the serialization unit tests today.

On Wed, Dec 24, 2014 at 12:22 AM, Thomas <tzav...@gmail.com> wrote:
Thanks, yes, like I said - I already tried that and it solves the problem, but I was hoping I won't be forced to replace all my IEnumerable definitions throughout the model just to be able to pass it through the queue. I was hoping there was another workaround.


--
You received this message because you are subscribed to the Google Groups "masstransit-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to masstransit-dis...@googlegroups.com.
To post to this group, send email to masstrans...@googlegroups.com.

Travis Smith

unread,
Dec 24, 2014, 3:33:51 PM12/24/14
to masstrans...@googlegroups.com
The assumptions you can make about IList and arrays don't always apply to IEnumerable. This may cause you headaches at some point, so just remember what you are implying exists in that IEnumerable. 
To view this discussion on the web visit https://groups.google.com/d/msgid/masstransit-discuss/CAHX4WYdS-HGadANp4dQpz_Fuh0VRH5%3DXFsteiNxt8yh_Kt4DjQ%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.


--
-Travis

Chris Patterson

unread,
Dec 24, 2014, 7:08:34 PM12/24/14
to masstrans...@googlegroups.com
The real problem is that other types are IEnumerable, such as string (IEnumerable<char>) - so this makes it complicated and can result is some nasty results by making IEnumerable<T> serializable.

Reply all
Reply to author
Forward
0 new messages