Foxtrek_64 Foxtrek_64 - 6 months ago 30
JSON Question

JSON.net Deserialization with unique types

Before I start off - I should say I have very little experience with JSON. All of my experience with this has been with SnakeYaml in Java...

Secondly, if you think it is better to pursue a secondary solution for this project, please let me know...

I have a TCP server which accepts a json-formatted string and returns a json formatted string containing the requested information. Here's an example of what it'd be doing.

Request

{
'MyName': 'John Doe'
'MandatoryLookup': false
}


Response

{
'John Doe': {
'Location' : 'Big Office Building'
'Additional': 'Floor 2'
}
}


This part is working correctly and is provided only for understanding.

Rerailing, the server that provides the response returns this information after completing a SQL query. What I would like it to do is to save this query within memory (using a custom object made below) as well as storing it in a json file on disk. When the server boots, I'd like it to read from this json file and deserialize it into my objects. This way, it can return a response almost right away instead of having to perform a lookup every time. In the case that the server does not have the information on hand or the "MandatoryLookup" flag is
true
, it queries the SQL server for the response.

Here's the class for the custom object:

public class DataContainer
{
public string UserName { get; set; }
public info LocationInfo locationInfo;
}

public class LocationInfo
{
public string BuildingName { get; set; }
public string AdditionalInfo { get; set; }
}


^ The idea above goes to another StackOverflow thread I'd read regarding subcategories, though I don't know if this is correct provided the JSON string below.

RecentLookups.json ((This is the file saved to disk that I parse on startup))

{
'John Doe' : {
'Location' : 'Big Office Building',
'Additional' : 'Floor 2'
},
'Jane Doe' : {
'Location' : 'Small Office Building',
'Additional' : 'Security Office'
}
}


This ultimately splits into three questions


  1. What would be the best place to start when looking at how to format my object for deserialization (because the way it is now doesn't work).

  2. Is worrying about pre-caching the formatted sql queries to disk worth the trouble (is the SQL lookup going to be fast enough to just have it look up the value every time)?

  3. How would I go about programmatically creating a uniquely named DataContainer object for each Json group? -- Example below



The names of my JSON groups are not repeatable names -- that is, there will not be a group with a name like 'Jane Doe'. Instead, these examples were provided for readability. The real group names are unique identifiers for objects and the subcategories (location, additional) are information about said objects. What I would like is for each DataContainer object to have a unique name based off of the JSON category name, e.g. 'Jane Doe' would be
DataContainer JaneDoe
with the properties of that object set within.

Sorry for the wall and thanks in advance.

dbc dbc
Answer

You can deserialize that JSON to a Dictionary<string, LocationInfo>:

var dictionary = JsonConvert.DeserializeObject<Dictionary<string, LocationInfo>>(jsonString);

See Deserialize a Dictionary. Then you can convert to your final model if desired:

var list = dictionary.Select(pair => new DataContainer { UserName = pair.Key, locationInfo = pair.Value }).ToList();

In addition, since the c# POCO property names in your LocationInfo do not match the names in the JSON you are receiving, you need to manually set up the mapping using the [JsonProperty] attribute:

public class LocationInfo
{
    [JsonProperty("Location")]
    public string BuildingName { get; set; }
    [JsonProperty("Additional")]
    public string AdditionalInfo { get; set; }
}