using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System.Text.RegularExpressions;
using System.Collections.Generic;
public static void Main()
var responseData = "[{\"Channels\":[{\"Channel\":55,\"DataRate\":60,\"Offset\":0,\"PreScaled\":{\"Flags\":null,\"Reading\":4.809,\"ValidPercentage\":100},\"RedactedPercentage\":0,\"Scaled\":{\"Flags\":null,\"Reading\":4.809,\"ValidPercentage\":100},\"SensorLabel\":\"FLOW\",\"SensorName\":\"Flow\",\"Slope\":1,\"UniqueId\":685100,\"UnitName\":\"Litres Per Minute\"},{\"Channel\":57,\"DataRate\":60,\"Offset\":0,\"PreScaled\":{\"Flags\":null,\"Reading\":60.43,\"ValidPercentage\":100},\"RedactedPercentage\":0,\"Scaled\":{\"Flags\":null,\"Reading\":60.43,\"ValidPercentage\":100},\"SensorLabel\":\"HUM\",\"SensorName\":\"Humidity\",\"Slope\":1,\"UniqueId\":685100,\"UnitName\":\"Percent\"}],\"Location\":{\"Altitude\":null,\"Latitude\":52.20175,\"Longitude\":-1.7266},\"Timestamp\":{\"Convention\":\"TimeBeginning\",\"Timestamp\":\"2023-05-29T10:23:00+00:00\"}},{\"Channels\":[{\"Channel\":55,\"DataRate\":60,\"Offset\":0,\"PreScaled\":{\"Flags\":null,\"Reading\":4.803,\"ValidPercentage\":100},\"RedactedPercentage\":0,\"Scaled\":{\"Flags\":null,\"Reading\":4.803,\"ValidPercentage\":100},\"SensorLabel\":\"FLOW\",\"SensorName\":\"Flow\",\"Slope\":1,\"UniqueId\":685100,\"UnitName\":\"Litres Per Minute\"}],\"Location\":{\"Altitude\":null,\"Latitude\":52.20175,\"Longitude\":-1.7266},\"Timestamp\":{\"Convention\":\"TimeBeginning\",\"Timestamp\":\"2023-05-29T10:22:00+00:00\"}}]";
ReferenceStationData jsonLatestData = JsonConvert.DeserializeObject<ReferenceStationData>(responseData, new JsonSerializerSettings{DateTimeZoneHandling = DateTimeZoneHandling.Utc});
[JsonConverter(typeof(JsonPathConverter))]
public class ReferenceStationData
[JsonProperty("Timestamp.Timestamp")]
public DateTime TBTimestamp { get; set; }
[JsonProperty("Location.Latitude")]
public decimal? Latitude { get; set; }
[JsonProperty("Location.Longitude")]
public decimal? Longitude { get; set; }
[JsonProperty("Location.Altitude")]
public decimal? Altitude { get; set; }
public List<Sensor_Data> Channels { get; set; }
[JsonConverter(typeof(JsonPathConverter))]
[JsonProperty("Channel")]
public int? Channel { get; set; }
[JsonProperty("SensorName")]
public string Sensor_Name { get; set; }
[JsonProperty("SensorLabel")]
public string Sensor_Label { get; set; }
[JsonProperty("PreScaled.Reading")]
public decimal? PreScaled { get; set; }
[JsonProperty("Scaled.Reading")]
public decimal? Scaled { get; set; }
[JsonProperty("UnitName")]
public string Unit_Name { get; set; }
public decimal Slope { get; set; }
public decimal Offset { get; set; }
[JsonProperty("Scaled.Flags")]
public List<string> Flag { get; set; }
class JsonPathConverter : JsonConverter
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
JObject jo = JObject.Load(reader);
object targetObj = Activator.CreateInstance(objectType);
foreach (PropertyInfo prop in objectType.GetProperties().Where(p => p.CanRead && p.CanWrite))
JsonPropertyAttribute att = prop.GetCustomAttributes(true).OfType<JsonPropertyAttribute>().FirstOrDefault();
string jsonPath = att != null ? att.PropertyName : prop.Name;
if (serializer.ContractResolver is DefaultContractResolver)
var resolver = (DefaultContractResolver)serializer.ContractResolver;
jsonPath = resolver.GetResolvedPropertyName(jsonPath);
if (!Regex.IsMatch(jsonPath, @"^[a-zA-Z0-9_.-]+$"))
JToken token = jo.SelectToken(jsonPath);
if (token != null && token.Type != JTokenType.Null)
object value = token.ToObject(prop.PropertyType, serializer);
prop.SetValue(targetObj, value, null);
public override bool CanConvert(Type objectType)
public override bool CanWrite
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
throw new NotImplementedException();