Search code examples
c#xmljsonjson.netxelement

Convert XElement to JObject without JSON -or- Configure SerializeXNode for Empty Elements


I am using Json.NET's ability to convert XML to JSON and it works pretty well. I say "pretty well" because it will map empty XML nodes to null instead of {} (empty JSON object). However, because this web-services result drives a knockout.js binding, I need empty XML elements to map to {} in order to maintain the binding structure1.

The current approach looks like:

// Json.NET XML->JSON
// Can I specify any custom converters for this?
var json = Newtonsoft.Json.JsonConvert.SerializeXNode(xDoc);

// JSON->JObject
var jObject = Newtonsoft.Json.JsonConvert.DeserializeObject(json);

// Update all `null` values to `{}`
// This "works reliably" because XML properties can never be null, but is
// hackish in its own right.
ConvertNullToEmptyObject(jObject as JContainer);

// And we're back at JSON, but I'd like to avoid such
// a complicated XML->JSON->JObject(Fixup)->JSON route.
// Performance isn't an issue, but it just feels dirty.
var finalJson = Newtonsoft.Json.JsonConvert.SerializeObject(jObject);

So then (the questions!);

  1. How can the roundabout trip through JSON be avoided?
  2. Is there a better way to convert an XElement to JSON (applying special rules) to begin with?

Notes:

  • I am aware I could write my own XElement->JObject conversion function (using the same rules, or even code, as Json.NET), but I would like to re-use library support if possible. If you think I should just do this to start with, leave a comment saying so.
  • I would like to stick to Json.NET, but would not be dissuaded from looking at alternative or supplemental libraries as long as they are free, small, and work in .NET 3.5.

1 The general approach of knockout<-JSON<-WS(XML)->JSON->knockout works quite well. This issue here is that standard knockout.js template bindings (in conjunction with ko.mapping) will not "auto-vivify" the structure even though binding to nonexistent properties (within an existing structure) works well.


Solution

  • If you have a better answer, write it. Accepted answers can be changed.


    Well, I'm going to say this is "not reasonably possible" with Json.NET.

    I cracked open Json.NET's XmlNodeConverter and it only interfaces externally with JsonReader and JsonWriter.

    While it would likely be possible to write a JObjectReader and a JObjectWriter, this would involve more work than I am currently willing to invest.

    Alternatively, I could copy all of the XmlNodeConverter code (most of it is private/internal) and modify it per my requirements - but this sort of copy'n'paste mass-duplication rubs me wrong.

    What I have now works well enough, even if does seem wasteful.