Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# JSON复杂类型,可以是对象或对象数组_C#_Arrays_Json_Object - Fatal编程技术网

C# JSON复杂类型,可以是对象或对象数组

C# JSON复杂类型,可以是对象或对象数组,c#,arrays,json,object,C#,Arrays,Json,Object,我试图处理一个对象,它可以是一个对象数组,也可以只是一个对象。仅当naics是对象而不是数组时,使用下面的代码才有效。我做错了什么 下面是我能想到的最简短的例子: [{ "section": "52.219-1.b", "naics": [{ "naicsName": "Engineering Services", "isPrimary": true, "ExcpCou

我试图处理一个对象,它可以是一个对象数组,也可以只是一个对象。仅当naics是对象而不是数组时,使用下面的代码才有效。我做错了什么

下面是我能想到的最简短的例子:

[{
        "section": "52.219-1.b",
        "naics": [{
                "naicsName": "Engineering Services",
                "isPrimary": true,
                "ExcpCounter": 1,
                "isSmallBusiness": "Y",
                "naicsCode": 541330
            },
            {
                "naicsName": "Military and Aerospace Equipment and Military Weapons",
                "isPrimary": true,
                "ExcpCounter": 2,
                "isSmallBusiness": "Y",
                "naicsCode": 541330
            }
        ]
    },
    {
        "section": "52.219-1.b",
        "naics": {
            "naicsName": "Janitorial Services",
            "isPrimary": true,
            "isSmallBusiness": "Y",
            "naicsCode": 561720
        }
    }
]
我将只使用其中一种类型,但我在一个数组中强制使用两种类型,以将其强制为快速类型

我的课程是:

[JsonProperty("naics", NullValueHandling = NullValueHandling.Ignore)]
public AnswerNaics Naics { get; set; }

public partial struct AnswerNaics
{
    public AnswerNaic Naic;
    public AnswerNaic[] NaicArray;

    public static implicit operator AnswerNaics(AnswerNaic Naic) => new AnswerNaics { Naic = Naic };
    public static implicit operator AnswerNaics(AnswerNaic[] NaicArray) => new AnswerNaics { NaicArray = NaicArray };
}

public partial class AnswerNaic
{
    [JsonProperty("naicsName")]
    public string NaicsName { get; set; }

    [JsonProperty("hasSizeChanged")]
    public string HasSizeChanged { get; set; }

    [JsonProperty("isPrimary")]
    public bool IsPrimary { get; set; }

    [JsonProperty("ExcpCounter", NullValueHandling = NullValueHandling.Ignore)]
    public long? ExcpCounter { get; set; }

    [JsonProperty("isSmallBusiness")]
    public string IsSmallBusiness { get; set; }

    [JsonProperty("naicsCode")]
    public string NaicsCode { get; set; }
}

internal class NaicsConverter : JsonConverter
{
    public override bool CanConvert(Type t) => t == typeof(AnswerNaics) || t == typeof(AnswerNaics?);

    public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case JsonToken.StartObject:
                var objectValue = serializer.Deserialize<AnswerNaic>(reader);
                return new AnswerNaics { Naic = objectValue };
            case JsonToken.StartArray:
                var arrayValue = serializer.Deserialize<AnswerNaic[]>(reader);
                return new AnswerNaics { NaicArray = arrayValue };
        }
        throw new Exception("Cannot unmarshal type AnswerNaics");
    }

    public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
    {
        var value = (AnswerNaics)untypedValue;
        if (value.NaicArray != null)
        {
            serializer.Serialize(writer, value.NaicArray);
            return;
        }
        if (value.Naic != null)
        {
            serializer.Serialize(writer, value.Naic);
            return;
        }
        throw new Exception("Cannot marshal type Naics");
    }

    public static readonly NaicsConverter Singleton = new NaicsConverter();
}
[JsonProperty(“naics”,NullValueHandling=NullValueHandling.Ignore)]
公共应答Naics Naics{get;set;}
公共部分结构应答器
{
公众回答;
公共回答[]naikarray;
公共静态隐式运算符AnswerNaics(AnswerNaic Naic)=>新的AnswerNaics{Naic=Naic};
公共静态隐式运算符AnswerNaics(AnswerNaic[]NaicArray)=>新的AnswerNaics{NaicArray=NaicArray};
}
公共部分类应答器
{
[JsonProperty(“naicsName”)]
公共字符串NaicsName{get;set;}
[JsonProperty(“hasSizeChanged”)]
公共字符串hasizechanged{get;set;}
[JsonProperty(“iPrimary”)]
公共bool IsPrimary{get;set;}
[JsonProperty(“ExcpCounter”,NullValueHandling=NullValueHandling.Ignore)]
公共long?ExcpCounter{get;set;}
[JsonProperty(“isSmallBusiness”)]
公共字符串{get;set;}
[JsonProperty(“naicsCode”)]
公共字符串NaicsCode{get;set;}
}
内部类NaicConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型t)=>t==typeof(AnswerNaics)| | t==typeof(AnswerNaics?);
公共重写对象ReadJson(JsonReader阅读器,类型t,对象existingValue,JsonSerializer序列化程序)
{
开关(reader.TokenType)
{
案例JsonToken.StartObject:
var objectValue=serializer.Deserialize(读取器);
返回新的AnswerNaics{Naic=objectValue};
案例JsonToken.StartArray:
var arrayValue=序列化程序。反序列化(读取器);
返回新的应答{naikarray=arrayValue};
}
抛出新异常(“无法解组类型应答”);
}
public override void WriteJson(JsonWriter编写器、对象非类型化值、JsonSerializer序列化器)
{
var值=(AnswerNaics)非类型值;
如果(value.NaicArray!=null)
{
serializer.Serialize(writer,value.NaicArray);
返回;
}
如果(value.Naic!=null)
{
serializer.Serialize(writer,value.Naic);
返回;
}
抛出新异常(“无法封送Naics类型”);
}
public static readonly naicconverter Singleton=new naicconverter();
}

我有更多的对象或数组节点,但我只是想找出一个可以应用于所有这些节点的节点。

由于您无法更改传入的JSON,因此需要一个自定义转换器。比如说:

public class NaicsConverter : JsonConverter
{
    public override bool CanConvert(Type t) => t == typeof(Naics);

    public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
    {
        var naics = new Naics();

        switch (reader.TokenType)
        {
            case JsonToken.StartObject:
                // We know this is an object, so serialise a single Naics
                naics.Add(serializer.Deserialize<Naic>(reader));
                break;

            case JsonToken.StartArray:
                // We know this is an object, so serialise multiple Naics
                foreach(var naic in serializer.Deserialize<List<Naic>>(reader))
                {
                    naics.Add(naic);
                }
                break;
        }

        return naics;
    }

    public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
公共类NaicConverter:JsonConverter
{
公共覆盖bool CanConvert(类型t)=>t==typeof(Naics);
公共重写对象ReadJson(JsonReader阅读器,类型t,对象existingValue,JsonSerializer序列化程序)
{
var naics=新的naics();
开关(reader.TokenType)
{
案例JsonToken.StartObject:
//我们知道这是一个对象,所以序列化一个Naics
Add(序列化程序.反序列化(读取器));
打破
案例JsonToken.StartArray:
//我们知道这是一个对象,所以序列化多个NAIC
foreach(序列化程序中的var naic.反序列化(读取器))
{
添加(naic);
}
打破
}
返回naics;
}
public override void WriteJson(JsonWriter编写器、对象非类型化值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
}
以及支援课程:

public class Root
{
    public string Section { get; set; }

    [JsonConverter(typeof(NaicsConverter))]
    public Naics Naics { get; set; }
}

// This isn't ideal, but it's quick and dirty and should get you started
public class Naics : List<Naic>
{

}

public class Naic
{
    public string NaicsName { get; set; }
    public bool IsPrimary { get; set; }
    public string IsSmallBusiness { get; set; }
    public long NaicsCode { get; set; }
}
公共类根目录
{
公共字符串部分{get;set;}
[JsonConverter(类型(NAICconverter))]
公共Naics Naics{get;set;}
}
//这并不理想,但它又快又脏,应该让你开始
公共类Naics:列表
{
}
公共类Naic
{
公共字符串NaicsName{get;set;}
公共bool IsPrimary{get;set;}
公共字符串{get;set;}
公共长代码{get;set;}
}
最后,要反序列化:

var settings = new JsonSerializerSettings {Converters = {new NaicsConverter()}};

var root = JsonConvert.DeserializeObject<Root[]>(Json, settings);
var settings=newjsonserializersettings{Converters={new naicconverter()};
var root=JsonConvert.DeserializeObject(Json,设置);

现在,您的对象将被序列化到列表中,但作为单个项。

您可以使用类中的动态字段解决此问题

以JSON为例:

[
  {
    "field1": "val1",
    "nested": [
      {
        "nestedField": "val2"
      },
      {
        "nestedField": "val3"
      }
    ]
  },
  {
    "field1": "val4",
    "nested": 
      {
        "nestedField": "val5"
      }          
  }
]
nested
字段首先是一个包含两个对象的数组,第二个外观是一个对象。(类似于您发布的JSON)

因此,类表示形式如下所示:

    public class RootObject
    {
        public string field1 { get; set; }

        public dynamic nested { get; set; }  

        public List<NestedObject> NestedObjects
        {
            get
            {
               if(nested is JArray)
               {
                    return JsonConvert.DeserializeObject<List<NestedObject>>(nested.ToString());
               }

               var obj = JsonConvert.DeserializeObject<NestedObject>(nested.ToString());
               return new List<NestedObject> { obj };
            }
        }
    }

    public class NestedObject
    {
        public string nestedField { get; set; }
    }
公共类根对象
{
公共字符串字段1{get;set;}
公共动态嵌套{get;set;}
公共列表嵌套对象
{
得到
{
if(嵌套的是JArray)
{
返回JsonConvert.DeserializeObject(nested.ToString());
}
var obj=JsonConvert.DeserializeObject(nested.ToString());
返回新列表{obj};
}
}
}
公共类嵌套对象
{
公共字符串嵌套字段{get;set;}
}
使用Newtonsoft JSON反序列化代码非常简单:

var objectList = JsonConvert.DeserializeObject<List<RootObject>>("some_json");

foreach(var v in objectList)
{
    foreach(var n in v.NestedObjects)
    {
        Console.WriteLine(n.nestedField);
    }
}
var objectList=JsonConvert.DeserializeObject(“some_json”);
foreach(objectList中的var v)
{
foreach(v.NestedObjects中的变量n)
{
控制台写入线(n.nestedField);
}
}
唯一的更改是
NestedObjects
ready only属性的实现。它检查动态对象是否为
J