Reputation: 418
I have in such an json object:
{
"status": "Success",
"value": [
[
"2019-10-21T11:48:00Z",
"010719/360",
"[email protected]",
{
"role": "hodler",
"company": "Proximus",
"first_name": "Ivan",
"last_name": "Holms",
"modification_date": "2019-10-21 10:33:39"
}
]
]
}
Before that, I always used var obj = JsonConvert.DeserializeObject<MyDistClass>(json);
But I do not understand how to describe this entity:
"value": [
[
"2019-10-21T11:48:00Z",
"010719/360",
"[email protected]",
{
"role": "holder",
"company": "Proximus",
"first_name": "Marc",
"last_name": "Neukirch",
"modification_date": "2019-10-21T10:33:39"
}
]
]
I tried all the classes I knew, even tried to substitute the tuple, but without result. Help me please.
Upvotes: 2
Views: 666
Reputation: 3071
I was able to generate a converter with
Seems to work pretty well.
Here's the Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace QuickType
{
public partial class Request
{
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("value")]
public ValueElement[][] Value { get; set; }
}
public partial class ValueClass
{
[JsonProperty("role")]
public string Role { get; set; }
[JsonProperty("company")]
public string Company { get; set; }
[JsonProperty("first_name")]
public string FirstName { get; set; }
[JsonProperty("last_name")]
public string LastName { get; set; }
[JsonProperty("modification_date")]
public DateTimeOffset ModificationDate { get; set; }
}
public partial struct ValueElement
{
public string String;
public ValueClass ValueClass;
public static implicit operator ValueElement(string String) => new ValueElement { String = String };
public static implicit operator ValueElement(ValueClass ValueClass) => new ValueElement { ValueClass = ValueClass };
}
internal static class Converter2
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
Converters =
{
ValueElementConverter.Singleton,
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
},
};
}
internal class ValueElementConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(ValueElement) || t == typeof(ValueElement?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.String:
case JsonToken.Date:
var stringValue = serializer.Deserialize<string>(reader);
return new ValueElement { String = stringValue };
case JsonToken.StartObject:
var objectValue = serializer.Deserialize<ValueClass>(reader);
return new ValueElement { ValueClass = objectValue };
}
throw new Exception("Cannot unmarshal type ValueElement");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
var value = (ValueElement)untypedValue;
if (value.String != null)
{
serializer.Serialize(writer, value.String);
return;
}
if (value.ValueClass != null)
{
serializer.Serialize(writer, value.ValueClass);
return;
}
throw new Exception("Cannot marshal type ValueElement");
}
public static readonly ValueElementConverter Singleton = new ValueElementConverter();
}
}
Deserialize like this:
var myObject = JsonConvert.DeserializeObject<Request>(json, Converter2.Settings);
Upvotes: 2
Reputation: 1503140
I would probably use Json.NET to parse the JSON to a JObject
, then extract the relevant values from that - using JToken.ToObject<>
where possible.
Here's some sample code that appears to work - but needs a lot of validation and general tidying up. It's more about demonstrating the idea than anything else:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Program
{
static void Main(string[] args)
{
string json = File.ReadAllText("test.json");
Result result = Result.FromJson(json);
Console.WriteLine(result.Status);
Console.WriteLine(result.Values.Count);
Console.WriteLine(result.Values[0].User.FirstName);
}
}
public sealed class Result
{
public string Status { get; }
public IReadOnlyList<ResultValue> Values { get; }
private Result(string status, IReadOnlyList<ResultValue> values) =>
(Status, Values) = (status, values);
public static Result FromJson(string json)
{
JObject parsed = JObject.Parse(json);
string status = (string) parsed["status"];
JArray array = (JArray) parsed["value"];
var values = array.Select(ResultValue.FromJToken).ToList().AsReadOnly();
return new Result(status, values);
}
}
public sealed class ResultValue
{
public DateTime Timestamp { get; }
public string Id { get; }
public string Email { get; }
public User User { get; }
private ResultValue(DateTime timestamp, string id, string email, User user) =>
(Timestamp, Id, Email, User) = (timestamp, id, email, user);
internal static ResultValue FromJToken(JToken token)
{
JArray array = (JArray) token;
DateTime timestamp = (DateTime) array[0];
string id = (string) array[1];
string email = (string) array[2];
User user = array[3].ToObject<User>();
return new ResultValue(timestamp, id, email, user);
}
}
// TODO: Make this immutable, or everything else immutable
public sealed class User
{
[JsonProperty("role")]
public string Role { get; set; }
[JsonProperty("company")]
public string Company { get; set; }
[JsonProperty("first_name")]
public string FirstName { get; set; }
[JsonProperty("last_name")]
public string LastName { get; set; }
[JsonProperty("modification_date")]
public DateTime ModificationDate { get; set; }
}
Upvotes: 4