#c# #json.net #hierarchy
#c# #json.net #иерархия
Вопрос:
У меня есть объект, который заполняется через пользовательский JsonConverter
. В нем есть другой объект, внутри которого я хочу передать / поделиться свойством основного объекта.
Weather.cs
[JsonConverter(typeof(JsonPathConverter))]
public class Weather
{
public DateTime RequestDate { get; set; }
[JsonProperty(PropertyName = "timezone_offset")]
public int TimezoneOffset { get; set; }
[JsonProperty(PropertyName = "current")]
public Current Current { get; set; }
}
Текущий
[JsonConverter(typeof(JsonPathConverter))]
public class Current
{
[JsonProperty(PropertyName = "dt")]
public int Timestamp { get; set; }
public string FormattedDate()
{
string response = string.Empty;
// Here's where I want to access TimezoneOffset
return response;
}
// More stuff...
}
JsonPathConverter
public 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 amp;amp; p.CanWrite))
{
JsonPropertyAttribute att = prop.GetCustomAttributes(true)
.OfType<JsonPropertyAttribute>()
.FirstOrDefault();
string jsonPath = (att != null ? att.PropertyName : prop.Name);
JToken token = jo.SelectToken(jsonPath);
if (token != null amp;amp; token.Type != JTokenType.Null)
{
object value = token.ToObject(prop.PropertyType, serializer);
prop.SetValue(targetObj, value, null);
}
}
return targetObj;
}
public override bool CanConvert(Type objectType)
{
return true;
}
public override bool CanWrite
{
get { return true; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value.GetType().IsGenericType amp;amp; value is IEnumerable)
{
JArray result = new JArray();
IEnumerable list = value as IEnumerable;
foreach(var obj in list)
result.Add(GetObjectJson(obj));
result.WriteTo(writer);
}
else
{
JObject result = GetObjectJson(value);
result.WriteTo(writer);
}
}
private JObject GetObjectJson(object obj)
{
JObject jObj = new JObject();
if (obj != null)
{
PropertyInfo[] props = obj.GetType().GetProperties();
foreach (PropertyInfo prop in props)
{
if (prop.PropertyType.ToString().Contains("System") || prop.PropertyType.ToString().Contains("Json"))
jObj.Add(char.ToLowerInvariant(prop.Name[0]) prop.Name.Substring(1), JToken.FromObject(prop.GetValue(obj)));
else
jObj.Add(char.ToLowerInvariant(prop.Name[0]) prop.Name.Substring(1), GetObjectJson(prop.GetValue(obj)));
}
}
return jObj;
}
}
Я пробовал использовать иерархию, но при сериализации JSON создается пустой текущий объект.
Обновить
Чтобы было более понятно, вот пример того, как я использую это:
Я создаю HttpRequest
, который возвращает JSON, подобный этому:
{
"timezone_offset": 7200,
"current": {
"dt": 1600242501,
"sunrise": 1600234796,
"sunset": 1600279440,
"temp": 24.85,
"feels_like": 26.84,
"pressure": 1019,
"humidity": 78,
"dew_point": 20.75,
"uvi": 7.42,
"clouds": 2,
"visibility": 10000,
"wind_speed": 2.96,
"wind_deg": 66,
"weather": [{
"id": 800,
"main": "Clear",
"description": "cielo claro",
"icon": "01d"
}]
}
}
Затем я десериализую ее в Weather
объект:
Weather weather = JsonConvert.DeserializeObject<Weather>(json.ToString());
Она заполняет как Weather
, так и Current
объекты, поскольку Current
object является свойством Weather
самого себя.
Затем, когда я хочу вернуть Weather
объект, я делаю это следующим образом:
JObject.Parse(JsonConvert.SerializeObject(weather, Formatting.Indented, new JsonPathConverter()))
В этот момент я хочу вернуть новое поле FormattedDate
в Current
объекте, которое вычисляется. Я делал это раньше, и это работает, проблема сейчас в том, что я хочу, чтобы он использовал родительское свойство TimezoneOffset
в этом поле.
Комментарии:
1. Почему и как вы хотите «получить доступ» к timezoneOffset?
2. @Fildor ну, я хочу вернуть строку с отформатированной датой. Поскольку это может быть дата из любого места, я должен применить смещение, чтобы получить правильное datetime.
3. @Sinatr Я не уверен, что ты мне говоришь.
4. У @JohnG
Weather
естьCurrent
свойство объекта, которое я хочу использоватьWeather.TimezoneOffset
внутри этогоCurrent
свойства.5. Вы добавляете метод в DTO и, согласно редактированию, это должно быть свойство . Просто десериализуйте
Weather
, присвоите новое значение новому свойству и сериализуйте. Вам не нужны ссылки или преобразователи.