简体   繁体   English

如何将具有多个字符串属性的对象序列化为每个具有一个字符串属性的对象的 json 数组?

[英]How to serialize an object with multiple string properties to a json array of objects with one string property each?

I have list of Property classes that looks like this:我有如下所示的Property类列表:

public class RootObject
{
    public List<Property> Properties { get; set; }
}

public class Property
{
    public string MyFirstProp { get; set; }
    public string MySecondProp {get; set; }
}

When serialized using Json.NET, the output is this:使用 Json.NET 进行序列化时,输出如下:

{
   "Properties":[
      {
         "MyFirstProp":"Hello",
         "MySecondProp":"World"
      }
   ]
}

I would need the output to look like this:我需要输出如下所示:

{
   "Properties":[
      {
         "MyFirstProp":"Hello"
      },
      {
         "MySecondProp":"World"
      }
   ]
}

How can I accomplish this?我怎样才能做到这一点?

You can introduce a custom JsonConverter<Property> that serializes Property instances as arrays of single-property objects, rather than as a single object:您可以引入一个自定义JsonConverter<Property> ,它将Property实例序列化为单个属性对象的数组,而不是单个对象:

public class ObjectAsObjectArrayConverter<TObject> : JsonConverter<TObject>
{
    public override void WriteJson(JsonWriter writer, TObject value, JsonSerializer serializer)
    {
        var contract = (serializer.ContractResolver.ResolveContract(value.GetType()) as JsonObjectContract) ?? throw new ArgumentException("Wrong contract type");
        writer.WriteStartArray();
        foreach (var property in contract.Properties.Where(p => ShouldSerialize(p, value)))
        {
            var propertyValue = property.ValueProvider.GetValue(value);
            if (propertyValue == null && (serializer.NullValueHandling == NullValueHandling.Ignore || property.NullValueHandling == NullValueHandling.Ignore))
                continue;
            writer.WriteStartObject();
            writer.WritePropertyName(property.PropertyName);
            if (propertyValue == null)
                writer.WriteNull();
            else if (property.Converter != null && property.Converter.CanWrite)
                property.Converter.WriteJson(writer, propertyValue, serializer);
            else
                serializer.Serialize(writer, propertyValue);
            writer.WriteEndObject();
        }
        writer.WriteEndArray();
    }

    protected virtual bool ShouldSerialize(JsonProperty property, object value) =>
        property.Readable && !property.Ignored && (property.ShouldSerialize == null || property.ShouldSerialize(value));

    public override TObject ReadJson(JsonReader reader, Type objectType, TObject existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (existingValue == null)
            existingValue = (TObject)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();

        switch (reader.MoveToContentAndAssert().TokenType)
        {
            case JsonToken.Null:
                return (TObject)(object)null;
        
            case JsonToken.StartArray:
                while (reader.ReadToContentAndAssert().TokenType != JsonToken.EndArray)
                {
                    switch (reader.TokenType)
                    {
                        case JsonToken.StartObject:
                            serializer.Populate(reader, existingValue);
                            break;
                        default:
                            throw new JsonSerializationException("Unexpected token type " + reader.TokenType.ToString());
                    }
                }
                break;

            case JsonToken.StartObject:
                serializer.Populate(reader, existingValue);
                break;

            default:
                throw new JsonSerializationException("Unexpected token type " + reader.TokenType.ToString());
        }
        return existingValue;
    }
}

public static partial class JsonExtensions
{
    public static JsonReader ReadToContentAndAssert(this JsonReader reader) =>
        reader.ReadAndAssert().MoveToContentAndAssert();

    public static JsonReader MoveToContentAndAssert(this JsonReader reader)
    {
        if (reader == null)
            throw new ArgumentNullException();
        if (reader.TokenType == JsonToken.None)       // Skip past beginning of stream.
            reader.ReadAndAssert();
        while (reader.TokenType == JsonToken.Comment) // Skip past comments.
            reader.ReadAndAssert();
        return reader;
    }

    public static JsonReader ReadAndAssert(this JsonReader reader)
    {
        if (reader == null)
            throw new ArgumentNullException();
        if (!reader.Read())
            throw new JsonReaderException("Unexpected end of JSON stream.");
        return reader;
    }
}

Then modify RootObject as follows, replacing public List<Property> Properties with a single public Property Properties :然后按如下方式修改RootObject ,将public List<Property> Properties替换为单个public Property Properties

public class RootObject
{
    public Property Properties { get; set; }
}

And serialize by adding the converter to JsonSerializerSettings.Converters :并通过将转换器添加到JsonSerializerSettings.Converters进行序列化:

var settings = new JsonSerializerSettings
{
    Converters = { new ObjectAsObjectArrayConverter<Property>() },
};
var json = JsonConvert.SerializeObject(myClass, Formatting.Indented, settings);

And you will get:你会得到:

{
  "Properties": [
    {
      "MyFirstProp": "Hello"
    },
    {
      "MySecondProp": "World"
    }
  ]
}

Demo fiddle here .演示小提琴在这里

to create the output you need, you have to use this code要创建您需要的输出,您必须使用此代码

    var props = new Root {
    Properties = new List<Dictionary<string, string>>
    {
        new Dictionary<string,string> { { "MyFirstProp","Hello"}},
        new Dictionary<string,string> { { "MySecondProp","World"}}
    }};

    var json = JsonConvert.SerializeObject(props, Newtonsoft.Json.Formatting.Indented);

public class Root
{
    public List<Dictionary<string, string>> Properties { get; set; }
}

result结果

{
  "Properties": [
    {
      "MyFirstProp": "Hello"
    },
    {
      "MySecondProp": "World"
    }
  ]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将对象数组作为一个对象序列化,并在C#中使用JSON序列化程序为每个对象指定一个命名属性 - Serialize array of objects as one object with a named property for each object in C# with JSON serializer 如何序列化具有多个 object 类型的 json 字符串? - How to Serialize a json string with multiple object types? 序列化为对象的JSON数组<string, string> - Serialize to JSON Array of object<string, string> 序列化对象的属性以分离数组中的JSON对象 - Serialize an object's properties to separate JSON objects in an array JSON.NET:将 json 字符串属性序列化为 json 对象 - JSON.NET: Serialize json string property into json object 如何使用Json.Net将对象序列化为JSON字符串属性而不是对象 - How to serialize an object to a JSON string property instead of an object using Json.Net 如何将字符串序列化为 JSON 并按其中一个值分组? - How to serialize a string into JSON and group by one of the values? 如何将 FileStream object 序列化为 JSON 字符串? - How to serialize FileStream object to JSON string? 如何将 object 中的字符串序列化为有效的 json? - How to serialize string inside object as valid json? 如何序列化列表 <object> 到JSON属性集(不是JSON数组) - How to serialize a List<object> to JSON set of properties (not JSON array)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM