You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

第三方API嵌套JSON结构变体适配方案咨询:Property3为对象/数组时优雅获取目标值

Handling Inconsistent JSON Structures (Object vs Array) in Json.NET

Great question! Dealing with API responses that flip between object and array types for the same field is a super common headache, and you don’t need to rely on two separate models plus error handling to solve it. Here are a few elegant, no-preprocessing solutions:

Option 1: Use JToken for Dynamic Traversal (Most Flexible)

Instead of sticking to a strict strongly-typed model, use Json.NET's JObject and JToken to dynamically navigate the JSON structure. This lets you check whether Property3 is an object or array on the fly:

using Newtonsoft.Json.Linq;

// Parse the raw JSON string
var jObject = JObject.Parse(MyJsonString);

// Locate Property3 and handle both object/array cases
var property3Token = jObject["Property1"]["Property2B"]["Property3"];
JToken targetProperty3 = property3Token.Type == JTokenType.Array 
    ? property3Token.First() // Take the first element if it's an array
    : property3Token; // Use directly if it's an object

// Extract the desired value
string result = targetProperty3["Property4"]["Property5"]["Property6"][1]["Property7D"]["X"].Value<string>();

You can even condense this with SelectToken for cleaner code:

var result = jObject.SelectToken("$.Property1.Property2B.Property3")
                   .SelectToken(token => token.Type == JTokenType.Array ? token[0] : token)
                   .SelectToken("Property4.Property5.Property6[1].Property7D.X")
                   .Value<string>();

Option 2: Update Your Strongly-Typed Model with a Custom Converter

If you want to keep using your existing model structure, create a custom JsonConverter that handles both object and array cases for Property3. This way, deserialization will automatically normalize the structure for you:

Step 1: Update Your Model

Add the converter attribute to the Property3 field in your Property2B class:

public class Property2B
{
    [JsonConverter(typeof(SingleItemOrArrayConverter<Property3>))]
    public Property3 Property3 { get; set; }
}

// Keep your existing Rootobject, Property1, Property3, Property4, etc. classes unchanged

Step 2: Implement the Custom Converter

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;

public class SingleItemOrArrayConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(T);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        // If it's an array, deserialize the first element; otherwise deserialize the object directly
        return token.Type == JTokenType.Array 
            ? token.First().ToObject<T>(serializer) 
            : token.ToObject<T>(serializer);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // Optional: If you need to serialize back to JSON, adjust this to match your API's expected format
        serializer.Serialize(writer, value);
    }
}

Now your original deserialization code works for both JSON variants:

Rootobject obj = JsonConvert.DeserializeObject<Rootobject>(MyJsonString);
string result = obj.Property1.Property2B.Property3.Property4.Property5.Property6[1].Property7D.X;

Option 3: Use dynamic (Quick but Unsafe)

For a quick-and-dirty solution (not recommended for production code due to lack of type safety), you can use dynamic to bypass strict typing:

dynamic obj = JsonConvert.DeserializeObject(MyJsonString);
dynamic property3 = obj.Property1.Property2B.Property3;

// Check if Property3 is an array and grab the first element if needed
var targetProperty3 = property3 is System.Collections.IEnumerable ? property3[0] : property3;
string result = targetProperty3.Property4.Property5.Property6[1].Property7D.X;

Recommendation

If you prefer flexibility and don’t mind moving away from strict models, go with Option 1. If you want to maintain type safety and keep using your existing model structure, Option 2 is the most robust choice. Both avoid JSON preprocessing and messy error-handling switches between models.

内容的提问来源于stack exchange,提问作者Michael Plevan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 12:42:30