Skip to content

Instantly share code, notes, and snippets.

@deanebarker
Last active September 6, 2024 14:45
Show Gist options
  • Save deanebarker/d9983155603d1adf26197787a9c74ae4 to your computer and use it in GitHub Desktop.
Save deanebarker/d9983155603d1adf26197787a9c74ae4 to your computer and use it in GitHub Desktop.
A combined search and deserialization library using JSONata syntax
// Requires Nuget package Jsonata.Net.Native
// Doc here: https://deanebarker.net/tech/code/jsonata-doc/
public class JsonataDoc
{
// This is public so you can change the options if you want
public JsonSerializerOptions DeserializerOptions = new();
private string json;
public JsonataDoc(string input)
{
json = input;
DeserializerOptions.Converters.Add(new NullableDateTimeConverter());
DeserializerOptions.Converters.Add(new SafeStringTimeConverter());
DeserializerOptions.PropertyNameCaseInsensitive = true;
}
public string GetString(string query)
{
return GetObject<string>(query);
}
public double GetNumber(string query)
{
return GetObject<double>(query);
}
public DateTime? GetDate(string query)
{
return GetObject<DateTime?>(query);
}
public List<T> GetList<T>(string query)
{
return GetObject<List<T>>(query);
}
public List<Dictionary<string, string>> GetDictionaries(string query)
{
var result = GetResult(query);
var doc = JsonDocument.Parse(result);
var list = new List<Dictionary<string, string>>();
foreach (var item in doc.RootElement.EnumerateArray())
{
var thisItem = new Dictionary<string, string>();
foreach (var prop in item.EnumerateObject())
{
thisItem[prop.Name] = prop.Value.GetString();
}
list.Add(thisItem);
}
return list;
}
public string GetResult(string query)
{
var q = new JsonataQuery(query);
return q.Eval(json);
}
public T GetObject<T>(string query)
{
var result = GetResult(query);
return (T)DeserializeTo<T>(result);
}
private T DeserializeTo<T>(string json)
{
return (T)JsonSerializer.Deserialize(json, typeof(T), DeserializerOptions);
}
// This is so we don't break if a date string can't be parsed...
internal class NullableDateTimeConverter : JsonConverter<DateTime?>
{
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (DateTime.TryParse(reader.GetString(), out DateTime result))
{
return result;
}
return null;
}
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
// This is because the default JSON deserializer is too stupid to turn a number into a string...
internal class SafeStringTimeConverter : JsonConverter<string>
{
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.Number)
{
var value = reader.GetInt64();
return value.ToString();
}
return reader.GetString();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment