Newtonsoft Json Сериализация / десериализация вложенного свойства - PullRequest
0 голосов
/ 21 февраля 2019

У меня следующая структура класса

public class MainClass
{
   public string MyStringValue {get;set;}
   public SecondClass MyClassValue {get;set;}
}

public class SecondClass
{
   public string Value {get;set;}
}

Я устанавливаю следующие значения:

SecondClass secondClass = new SecondClass
{
   Value = "Test"
}

MainClass mainClass = new MainClass
{
   MyStringValue = "String Value",
   MyClassValue = secondClass
}

Когда я сериализую класс "mainClass", я получаю следующий Json (который абсолютноясно для меня):

{
  "MyStringValue":"String Value",
  "MyClassValue":
  {
     "Value":"Test"
  }
}

В некоторых случаях я хочу вместо этого сериализовать следующее:

{
  "MyStringValue":"String Value",
  "MyClassValue": "Test"
}

Имя поля подкласса всегда равно "Значение", Как это может быть сделано?(И мне также нужно иметь десериализуемый для той же структуры)

Ответы [ 4 ]

0 голосов
/ 21 февраля 2019

Одним из способов достижения этого является использование пользовательского JsonConverter с JsonConverterAttribute .Например, вы можете создать собственный конвертер для вашего класса:

public class SecondClassConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(SecondClass);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            if (reader.TokenType == JsonToken.String)
            {
                return new SecondClass
                {
                    Value = reader.Value.ToString()
                };
            }
        }
        catch (Exception ex)
        {
            throw new JsonSerializationException($"Error converting value {reader.Value} to type '{objectType}'.", ex);
        }

        throw new JsonSerializationException($"Unexpected token {reader.TokenType} when parsing {nameof(SecondClass)}.");
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        var secondClass = (SecondClass)value;
        writer.WriteValue(secondClass.Value);
    }
}

И затем вы будете использовать JsonConverterAttribute с этим конвертером:

public class MainClass
{
    public string MyStringValue { get; set; }
    [JsonConverter(typeof(SecondClassConverter))]
    public SecondClass MyClassValue { get; set; }
}

public class SecondClass
{
    public string Value { get; set; }
}

Это позволит разрешить все сериализацииMainClass для использования WriteJson метода SecondClassConverter:

static void Main(string[] args)
{
    SecondClass secondClass = new SecondClass
    {
        Value = "Test"
    };

    MainClass mainClass = new MainClass
    {
        MyStringValue = "String Value",
        MyClassValue = secondClass
    };

    var json = JsonConvert.SerializeObject(mainClass);

    Console.WriteLine(json);
    Console.ReadLine();
}

Предоставление желаемого результата JSON:

enter image description here


И десериализация также будет работать, используя ReadJson метод SecondClassConverter:

static void Main(string[] args)
{
    var json = "{ \"MyStringValue\":\"String Value\", \"MyClassValue\": \"Test\" }";

    var decodedJson = JsonConvert.DeserializeObject<MainClass>(json);

    Console.WriteLine($"decodedJson.MyStringValue: {decodedJson.MyStringValue}");
    Console.WriteLine($"decodedJson.MyClassValue.Value: {decodedJson.MyClassValue.Value}");
    Console.ReadLine();
}

Обеспечение вывода в виде:

enter image description here

0 голосов
/ 21 февраля 2019

Для этого вам нужен новый класс для десериализации.Однако для сериализации вы можете просто создать анонимный тип на лету, например:

void Main()
{
    // import Newtonsoft.JsonConvert

    SecondClass secondClass = new SecondClass
    {
        Value = "Test"
    };

    MainClass mainClass = new MainClass
    {
        MyStringValue = "String Value",
        MyClassValue = secondClass
    };

    // The JSON as you expect
    var origJson = JsonConvert.SerializeObject(mainClass);
    Console.WriteLine(origJson);
    // The JSON Deserialized and the second class value outputted
    Console.WriteLine(JsonConvert.DeserializeObject<MainClass>(origJson).MyClassValue.Value);

    // The modified JSON as you wanted it
    var modJson = JsonConvert.SerializeObject(new { mainClass.MyStringValue, MyClassValue = mainClass.MyClassValue.Value });
    Console.WriteLine(modJson);

    // The modified JSON deserialized
    var deserialized = JsonConvert.DeserializeObject<ModMainClass>(modJson);
    Console.WriteLine(deserialized.MyStringValue);
}

public class ModMainClass
{
    public string MyStringValue { get; set; }
    public string MyClassValue { get; set; }
}

public class MainClass
{
   public string MyStringValue {get;set;}
   public SecondClass MyClassValue {get;set;}
}

public class SecondClass
{
    public string Value { get; set; }
} 
0 голосов
/ 21 февраля 2019

У вас есть два варианта, один из которых @Simonare упомянул

или измените структуру вашего класса MainClass на

public class MainClass<T>
{
    public string MyStringValue { get; set; }
    public T MyClassValue { get; set; }
}

public class SecondClass
{
    public string Value { get; set; }
}

, и теперь вы можете просто выбрать, что использовать как MyClassValue

var c = new MainClass<string>();

Или

 var c = new MainClass<SecondClass>();
0 голосов
/ 21 февраля 2019

верхний JSON не совпадает с последним.Основной класс не может быть сериализован как {"MyStringValue":"String Value","MyClassValue": "Test"} без преобразования.

var resultObjet = new { 
     MyStringValue = mainClass.MyStringValue,
     MyClassValue = mainClass.SecondClass.MyClassValue
}

тогда вы можете сериализовать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...