Преобразование класса C # в Json с настраиваемой структурой - PullRequest
0 голосов
/ 12 декабря 2018

у нас есть класс C #, как показано ниже

public class PrimaryContact
{
   public string PrefixTitle { get; set; }

   public string SurName { get; set; }

   public string GivenName { get; set; }
}

нам нужно сериализовать объект json как

"primaryContact": {
      "prefixTitle": {
        "value": "mrs"
      },
      "surName": "abcd",
      "givenName": "abcd"      
    }

Обратите внимание: prefixTitle предназначен для значение * * 1 010.для некоторых выбранных атрибутов нам нужно сериализовать так.Также нам нужно читать из JSON и десериализовать в класс.Есть ли какой-нибудь общий лучший подход, которым мы можем следовать, украшая элементы, чтобы мы могли достичь этого результата?

Ответы [ 4 ]

0 голосов
/ 12 декабря 2018

Вам необходимо написать собственный сериализатор для вашего объекта.Вот пример, чтобы показать, как вы можете сделать это с расширением JsonConverter и использованием некоторого пользовательского атрибута, чтобы определить, должен ли ваш объект / свойство быть перенесен в:

[WrapperAttribute(Key = "primaryContact")]
public class PrimaryContact
{
    [WrapperAttribute(Key= "prefixTitle")]
    public string PrefixTitle { get; set; }

    public string SurName { get; set; }

    public string GivenName { get; set; }
}

public class WrapperAttribute : Attribute
{
    public string Key { get; set; }
}


public class WrapperSerializer : JsonConverter<PrimaryContact>
{
    public override void WriteJson(JsonWriter writer, PrimaryContact value, JsonSerializer serializer)
    {
        Type type = value.GetType();

        JObject root = new JObject();

        foreach (var property in type.GetAllProperties())
        {
            if (property.HasAttribute<WrapperAttribute>())
            {
                JProperty wrappedProperty = new JProperty(property.GetAttribute<WrapperAttribute>().Key);
                JObject wrappedChild = new JObject();
                wrappedProperty.Value = wrappedChild;

                JProperty wrappedChildProperty = new JProperty("value");
                wrappedChildProperty.Value = JToken.FromObject(property.GetValue(value));

                wrappedChild.Add(wrappedChildProperty);

                root.Add(wrappedProperty);
            }
            else
            {
                var childProperty = new JProperty(property.Name);

                childProperty.Value = JToken.FromObject(property.GetValue(value));
                root.Add(childProperty);
            }

        }

        if (type.HasAttribute<WrapperAttribute>())
        {
            JObject wrappedRoot = new JObject();
            var wrappedProperty = new JProperty(type.GetAttribute<WrapperAttribute>().Key);
            wrappedProperty.Value = root;
            wrappedRoot.Add(wrappedProperty);
            wrappedRoot.WriteTo(writer);
        }
        else
        {
            root.WriteTo(writer);
        }

    }

    public override PrimaryContact ReadJson(JsonReader reader, Type objectType, PrimaryContact existingValue, bool hasExistingValue,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

в main:

PrimaryContact contact = new PrimaryContact();
contact.GivenName = "test name";
contact.PrefixTitle = "test title";
contact.SurName = "test surname";

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new WrapperSerializer());

var serialized = JsonConvert.SerializeObject(contact, settings);

вывод:

{
    "primaryContact": {
        "prefixTitle": {
            "value": "test title"
        },
        "SurName": "test surname",
        "GivenName": "test name"
    }
}
0 голосов
/ 12 декабря 2018

Поскольку вы пометили свой вопрос , вы можете сделать это, применив custom JsonConverter к "выбранным атрибутам", которые должны быть вложены в {"value" : ... } объект при сериализации.

Сначала определите следующий конвертер:

public class NestedValueConverter<T> : JsonConverter
{
    class Value
    {
        public T value { get; set; }
    }

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        switch (reader.MoveToContent().TokenType)
        {
            case JsonToken.Null:
                return null;

            default:
                return serializer.Deserialize<Value>(reader).value;
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, new Value { value = (T)value });
    }
}

public static partial class JsonExtensions
{
    public static JsonReader MoveToContent(this JsonReader reader)
    {
        if (reader.TokenType == JsonToken.None)
            reader.Read();
        while (reader.TokenType == JsonToken.Comment && reader.Read())
            ;
        return reader;
    }
}

Теперь примените к нему «выбранные атрибуты» PrimaryContact следующим образом:

public class PrimaryContact
{
    [JsonConverter(typeof(NestedValueConverter<string>))]
    public string PrefixTitle { get; set; }

    public string SurName { get; set; }

    public string GivenName { get; set; }
}

И выбыть в состоянии десериализовать и сериализовать следующим образом:

var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
var root = JsonConvert.DeserializeObject<RootObject>(jsonString, settings);

var json2 = JsonConvert.SerializeObject(root, Formatting.Indented, settings);

Примечания:

  • Поскольку преобразователь предназначен для непосредственного применения с использованием атрибутов [JsonConverter(typeof(NestedValueConverter<...>))] или [JsonProperty(ItemConverterType = typeof(NestedValueConverter<...>))], CanConvert, который вызывается только тогда, когда преобразователь включен в настройки, не реализован.

  • Преобразователь является универсальным в случае, если вам нужно вложить не строковые значения.

Пример скрипта здесь .

0 голосов
/ 12 декабря 2018

Здесь префикс Заголовок Также класс не строка.Здесь ваш класс хочет выглядеть следующим образом.

public class PrimaryContact
{
   public PrefixTitle prefixTitle{ get; set; }

   public string surName{ get; set; }

   public string givenName{ get; set; }
}

public class PrefixTitle {
   public string value {get; set;}
}

Установите файл Newtonsoft.json libraby в свой проект: -> Откройте консоль диспетчера пакетов в Tools NuGet Package и вставьте ее, затем нажмите Enter .

Install-Package Newtonsoft.Json -Version 12.0.1

Преобразование класса в Json:

string output = JsonConvert.SerializeObject(classname);

Преобразование Json в объект:

Здесьобъект обозначает класс

Object output = JsonConvert.DeSerializeObject<object>(jsonString);

Здесь. Здесь вы можете найти оптимизированный код, который вы можете использовать в своем проекте напрямую:

public static string getJsonFromClass(object objectName){
    return JsonConvert.SerializeObject(object);
}

public static T getObjectFromJson<T>(string jsonString){
    T t = default(T);
    try{
       t = JsonConvert.DeSerializeObject<T>(classname);
    }catch(Exception e){
       Debug.WriteLine(e.Message);
    }
    return t;
}

. Этот метод можно использовать для получения результата:

string jsonData = getJsonFromClass(Prefix);

string JsonString = "<here your json string>";

Prefix getObjectFromJson = getObjectFromJson<Prefix>(JsonString);

вот и все ..

Надеюсь, это поможет вам ..

0 голосов
/ 12 декабря 2018

Вы можете добиться этого, изменив модель следующим образом:

public class PrimaryContact
{
   public Prefix PrefixTitle  { get; set; }

   public string SurName { get; set; }

   public string GivenName { get; set; }
}

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

Затем

Newton.Json.JsonConvert.DeserializeObject<PrimaryContact>();
...