I am building an interface to Cisco's ClearAccess application for my employer and I ran into something I found strange and wondered if anyone has suggestions on how to deal with it.
The JSON objects coming back from a simple invocation of "get me all what the customer has on their network" returns a great deal of information which can be easily de-serialized into some plan old objects until I found something like this in the mix:
"Settings.Hosts.35.Active":"false", "Settings.Hosts.17.Active":"false",
Essentially I have a big object that contains elements that follow the naming convention of "Settings.Hosts.xx.Active", "Settings.Hosts.xx.MACAddress", etc.
The documentation is sketchy at best from Cisco (even the object definitions are lacking) so I am left wondering if there's a maximum Host.xx I can safely rely upon or if there's a way I can bend JSON.NET to my will that will force these numbered elements into a collection of (conceptually) "Settings.Host" { "MACAddress": "xx:xx:xx:xx:xx", "Active": "false" }
I've considered using a custom parser (JsonProperty decoration), but I've been rather unsuccessful in finding examples of this to copy.
If you deserialize the JSON string to a JObject
, you could manipulate the object to rebuild it.
e.g.,
// suppose your string deserialized into this structure
var obj = new JObject(
new JProperty("Settings.Hosts.35.Active", false),
new JProperty("Settings.Hosts.35.MACAddress", "xx:xx:xx:xx:xx"),
new JProperty("Settings.Hosts.37.Active", false)
);
var re = new Regex(@"^Settings\.Hosts\.(\d+)\.(\w+)$");
var newObj = new JObject(
new JProperty("Settings.Hosts",
new JObject(
from prop in obj.Cast<JProperty>()
let m = re.Match(prop.Name)
where m.Success
let id = m.Groups[1].Value
let propertyName = m.Groups[2].Value
group new JProperty(propertyName, prop.Value) by id into g
select new JProperty(g.Key, new JObject(g))
)
)
);
Ideally the code would be in a JsonConverter
. This would yield the following JSON strings.
// before
{
"Settings.Hosts.35.Active": false,
"Settings.Hosts.35.MACAddress": "xx:xx:xx:xx:xx",
"Settings.Hosts.37.Active": false
}
// after
{
"Settings.Hosts": {
"35": {
"Active": false,
"MACAddress": "xx:xx:xx:xx:xx"
},
"37": {
"Active": false
}
}
}