Monday, February 7, 2011

What's the best way to serialize a HashTable for SOAP/XML?

What's the best way to serialize a HashTable (or a data best navigated through a string indexer) with SOAP/XML?

Let's say I have an Foo that has an property Bar[] Bars. A Bar object has a key and a value. By default, this serializes to the following XML:

<Foo>
<Bars>
<Bar key="key0" value="value0"/>
...
</Bars>
</Foo>

For JSON, this serializes to

{"Foo":["Bars":[{"Key":"key0","Value":"key1} ... ]}]}

What I'd really like to have is this serialize to better reflect the underlying relationship. E.g.,

<Foo>
<Bars>
<Key0 value="value0"/>
<Key1 value="value1"/>
...
</Bars>
</Foo>

I realize there are some challenges with serializing to SOAP in this way, but what's the best approach to providing a schema that better reflects this?

I've tried creating a BarsCollection object and defining custom serialization on that, but it doesn't seem to actually invoke the serialization on that object. E.g.,

void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
foreach (Bar bar in Bars)
info.AddValue(bar.Key. bar);
}

Any suggestions? What's the best practice here?

  • ISerializable isn't used for xml serialization; its used for binary serialization. You would be better implementing IXmlSerializable.

    But I think that the KeyedCollection serializes more like you're thinking. Except you'll never get <key0 ... /> <key1 ... /> since the elements map to classes.

    From Will
  • You could pass the hashtable in a SOAP Extension. That way, you can serialize it whichever way you would like. Although there is custom code for this that has to be on the client and server.

    tmarman : Yeah, I don't control the consumer so I need something that will work generically (and off the .NET platform).
  • I really don't think that what you want reflects the structure better. To define a schema (think XSD) for this you would have to know all of the potential keys in advance since you indicate that you want each one to be a separate custom type. Conceptually Bars would be an array of objects holding objects of type Key0, Key1, with each of the KeyN class containing a value property. I believe that the first serialization actually is the best reflection of the underlying structure. The reason it "works" more like you want in JSON is that you lose the typing -- everything is just an object. If you don't care about the types why not just use JSON?

    tmarman : Right - this is exactly the issue - there can be an infinite number of keys, different Foos can have different sets of them, etc. Obviously, on the backend I have this stored as a one-to-many relationship in the database - what I'm more concerned with now is making the API intuitive to use.
    tmarman : Regardless of how I've actually stored them, I want the consumer of the API to be able to have the syntactic nicety of it *looking* like an object with properties. Does that make sense?
    From tvanfosson
  • I think you're missing a fundamental key of the SOAP protocol.

    One of the things I really like about the SOAP protocol is that you can define arbitrary objects (along with methods) in your WSDL file and pass these objects around from one end to the other using the SOAP protocol. You don't have to serialize the data on one end and then unserialize it on the other end.

    tmarman : I don't quite understand what you're getting at. Obviously, I don't have to manually serialize since the runtime is doing that for me. I'm building an API here, so my goal is to make the serialized data look "nicer" by default in the consumer (which I don't control).
    From jsmith

0 comments:

Post a Comment