

配列が定義されたjsonから読み込んだ値を使用するプログラムを作成しています。

  * 値はjsonファイルに記載された値を使用する。
  * jsonファイルにプロパティ未記載の場合は配列の直前の要素の値を使用する。

以下のクラスでjsonファイル例をdeserializeすると未記載の場合は0となるため値として0を記載された場合に判定できず困っています。

[code]

    using System.text.Json;
    internal class Value
    {
        public int Front { get; set; }
        public int Back { get; set; }
    }
    
[/code]

jsonファイル例

[code]

    [
      {
        "Front": 2000,
        "Back": 2000,
      },
      {
        "Back": 3000,
      },
      {
        "Front": 0,
      }
    ]
    
[/code]


CC BY-SA 4.0
2022-07-08T09:19:36.213
89840
2022-07-10T02:39:38.747
2022-07-10T02:39:38.747
53441
53441
question
c# json
jsonファイルをdesirializeする際、値の記載がない場合の検知について


JSONのパーサーに何を使っているかにもよるのですが、一般的には[null許容値型](https://docs.microsoft.com/ja-
jp/dotnet/csharp/language-reference/builtin-types/nullable-value-
types)を使用するとnullかどうかで判定できることが多いです。  
具体的には以下のように変更してみてください。

[code]

    internal class Value
    {
      public int? Front { get; set; }
      public int? Back { get; set; }
    }
    
[/code]


CC BY-SA 4.0
2022-07-08T11:07:29.210
89843
2022-07-08T11:07:29.210
70
89840
answer


使っているデシリアライザが何だか不明ですが、System.Text.Json または Newtonsoft.Json を使うとして、

> jsonファイルにプロパティ未記載の場合は前回記載された値を使用する

の「前回記載された値」というのが何だか不明ですが配列の直前の要素の値を使うとして、さらに Value
クラスの定義は変更しないという条件で、以下のようにしてできると思います。.NET 6.0 のコンソールアプリです。

[code]

    #nullable disable
    using System.Text.Json;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    
    string json = @"[
      {
        ""Front"": 2000,
        ""Back"": 2000,
      },
      {
        ""Back"": 3000,
      },
      {
        ""Front"": 0,
      },
      {
        ""Front"": 555,
        ""Back"": 666,
      },
      {
      }
    ]";
    
    // System.Text.Json
    JsonElement jsonElement = System.Text.Json.JsonSerializer.Deserialize<JsonElement>(json,
        new JsonSerializerOptions
        {
            AllowTrailingCommas = true
        });
    List<Value> list1 = new List<Value>();
    if (jsonElement.ValueKind == JsonValueKind.Array)
    {
        int prevFront = -1;
        int prevBack = -1;
        bool isFrontSet, isBackSet;
        foreach (JsonElement jelemInArray in jsonElement.EnumerateArray())
        {
            if (jelemInArray.ValueKind == JsonValueKind.Object)
            {
                var value = new Value();
                isFrontSet = false;
                isBackSet = false;
                foreach (JsonProperty jprop in jelemInArray.EnumerateObject())
                {
                    if (jprop.Name == "Front")
                    {
                        value.Front = prevFront = jprop.Value.GetInt32();
                        isFrontSet = true;
                    }
                    if (jprop.Name  == "Back")
                    {
                        value.Back = prevBack = jprop.Value.GetInt32();
                        isBackSet = true;
                    }                
                }
    
                if (isFrontSet == false)
                {
                    value.Front = prevFront;
                    isFrontSet = true;
                }
                if (isBackSet == false)
                {
                    value.Back = prevBack;
                    isBackSet = true;
                }
    
                list1.Add(value);
            }
        }
    }
    
    // Newtonsoft.Json
    JToken jtoken = JsonConvert.DeserializeObject<JToken>(json);
    List<Value> list2 = new List<Value>();
    if (jtoken is JArray)
    {
        int prevFront = -1;
        int prevBack = -1;
        bool isFrontSet, isBackSet;
        foreach (JToken jtokenInArray in (JArray)jtoken)
        {
            if (jtokenInArray is JObject)
            {
                var value = new Value();
                isFrontSet = false;
                isBackSet = false;
                foreach (KeyValuePair<string, JToken> kvp in (JObject)jtokenInArray)
                {
                    if (kvp.Key == "Front")
                    {
                        value.Front = prevFront = (int)kvp.Value;
                        isFrontSet = true;
                    }
                    if (kvp.Key == "Back")
                    {
                        value.Back = prevBack = (int)kvp.Value;
                        isBackSet = true;
                    }
                }
    
                if (isFrontSet == false)
                {
                    value.Front = prevFront;
                    isFrontSet = true;
                }
                if (isBackSet == false)
                {
                    value.Back = prevBack;
                    isBackSet = true;
                }
    
                list2.Add(value);
            }
        }
    }
    
    public class Value
    {
        public int Front { get; set; }
        public int Back { get; set; }
    }
    
[/code]

結果は以下のようになります（Visual Studio のデバッグ画像）。

[![画像の説明をここに入力](https://i.stack.imgur.com/zPqnZ.jpg)](https://i.stack.imgur.com/zPqnZ.jpg)


CC BY-SA 4.0
2022-07-09T04:48:55.843
89852
2022-07-09T04:48:55.843
51338
89840
answer