Imagine a method accepting 2 string arguments:
public int Method(string expression, string variables) { ... }
"expression"
is expected to be a math. expression (e.g. "1 2") that needs to be evaluated. And if there's something except for numbers & operators, I need to look up for that variable
in "variables"
string argument, to replace that variable with the number it represents. (There's no guarantee that the variable is defined in "variables"
, but I believe it's not important here).
Input example:
Method("351 x", "{ \"x\":69 }");
// Expected output: 420
Example of other valid "variables"
values:
- { "x":123 }
- { "x":123, "y":420 }
- { }
- { "z":69 }
- { "abc": 777 }
I wonder what's a good way to parse & retrieve data from a JSON (that may have a different structure each time (i.e. different number of properties & names)), to map it with the variable
in "expression"
string?
CodePudding user response:
Personally, I would go with Newtonsoft.Json and use a mapping to a Dictionary<string, object>
:
using Newtonsoft.Json;
public int Method(string expression, string variables)
{
var varsDic =
JsonHelper.IsValidJson(variables)
? JsonConvert.DeserializeObject<Dictionary<string, object>>(variables);
: new Dictionary<string, object>()
// ...
}
With IsValidJson
being something like this:
public static class JsonHelper
{
public static bool IsValidJson(string json)
{
return IsValidJson(json, out _);
}
public static bool IsValidJson(string json, out Exception parseError)
{
if (string.IsNullOrWhiteSpace(json))
{
parseError = new Exception(Resources.JsonEmpty);
return false;
}
json = json.Trim();
if (json.StartsWith(@"{") && json.EndsWith(@"}") || //For object
json.StartsWith(@"[") && json.EndsWith(@"]")) //For array
{
try
{
JToken.Parse(json);
parseError = null;
return true;
}
catch (JsonReaderException x)
{
parseError = x;
return false;
}
catch (Exception x)
{
parseError = x;
return false;
}
}
else
{
parseError = new Exception(Resources.JsonNoStartEnd);
return false;
}
}