Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.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# 人口及;使用自定义iDefaultContractResolver从Json合并对象集合会导致数据移位/损坏_C#_Json_Json.net - Fatal编程技术网

C# 人口及;使用自定义iDefaultContractResolver从Json合并对象集合会导致数据移位/损坏

C# 人口及;使用自定义iDefaultContractResolver从Json合并对象集合会导致数据移位/损坏,c#,json,json.net,C#,Json,Json.net,这是我正在序列化/反序列化的类数据结构: public class SettingGroup { public string name { get; set; } public string description { get; set; } public bool visible { get; set; } public ObservableCollection<SettingGroup> groups { get; set; } publi

这是我正在序列化/反序列化的类数据结构:

public class SettingGroup
{
    public string name { get; set; }
    public string description { get; set; }
    public bool visible { get; set; }
    public ObservableCollection<SettingGroup> groups { get; set; }
    public ObservableCollection<Setting> settings { get; set; }
    public SettingGroup()
    {
        groups = new ObservableCollection<SettingGroup>();
        settings = new ObservableCollection<Setting>();
        visible = true;
    }
}

public class Setting
{
    public string name { get; set; }
    public string description { get; set; }
    public bool visible { get; set; }
    public DescriptionVisibility descriptionVisibility { get; set; }
    public Dictionary<string, dynamic> configuration { get; set; }
    public dynamic settingValue { get; set; }
    public SettingType settingType { get; set; }
    public SettingControl settingControl { get; set; }
    public Setting()
    {
        visible = true;
        configuration = new Dictionary<string, dynamic>();
    }
}
自定义iDefaultContractResolver是我在SE中看到的一个,但出于完整性考虑,这里将包括:

public class IgnorableSerializerContractResolver : DefaultContractResolver
{
    protected readonly Dictionary<Type, HashSet<string>> Ignores;

    public IgnorableSerializerContractResolver()
    {
        this.Ignores = new Dictionary<Type, HashSet<string>>();
    }

    public void Ignore(Type type, params string[] propertyName)
    {
        if (!this.Ignores.ContainsKey(type)) this.Ignores[type] = new HashSet<string>();

        foreach (var prop in propertyName)
        {
            this.Ignores[type].Add(prop);
        }
    }

    public bool IsIgnored(Type type, string propertyName)
    {
        if (!this.Ignores.ContainsKey(type)) return false;

        // if no properties provided, ignore the type entirely
        if (this.Ignores[type].Count == 0) return true;

        return this.Ignores[type].Contains(propertyName);
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (this.IsIgnored(property.DeclaringType, property.PropertyName)
        // need to check basetype as well for EF -- @per comment by user576838
        || this.IsIgnored(property.DeclaringType.BaseType, property.PropertyName))
        {
            property.ShouldSerialize = instance => { return false; };
        }

        return property;
    }
}
编辑以包含Json源和结果:

具有设置信息和默认值的完整Json结构:

{
  "name": "Application Settings",
  "description": "Common application settings.",
  "visible": true,
  "groups": [
    {
      "name": "General settings",
      "description": null,
      "visible": true,
      "groups": [
        {
          "name": "Startup settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Start IM with Windows",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            },
            {
              "name": "Start IM minimized",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        },
        {
          "name": "Performance settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Thread priority",
              "description": "This setting may not have a noticeible impact on all platforms, especially higer end ones.",
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {
                "lowVal": 0,
                "highVal": 7,
                "interval": 1
              },
              "settingValue": 3,
              "settingType": 0,
              "settingControl": 2
            }
          ]
        }
      ],
      "settings": []
    },
    {
      "name": "Theme settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "Update settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "General settings",
      "description": null,
      "visible": true,
      "groups": [
        {
          "name": "Startup settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Start IM with Windows",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            },
            {
              "name": "Start IM minimized",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        },
        {
          "name": "Performance settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Thread priority",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": 3,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        }
      ],
      "settings": []
    },
    {
      "name": "Theme settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "Update settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    }
  ],
  "settings": []
}
由my saveSettings扩展保存的数据,该扩展旨在仅保存所需的信息,如组名子项以及设置名称和值(看起来正确)

但当加载并与现有类对象合并时,结果数据就是这样的,请注意控件类型中的重复值和无效值会导致类型不匹配,即无法将
long
值加载到复选框使用的
bool

{
  "name": "Application Settings",
  "description": "Common application settings.",
  "visible": true,
  "groups": [
    {
      "name": "General settings",
      "description": null,
      "visible": true,
      "groups": [
        {
          "name": "Startup settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Start IM with Windows",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            },
            {
              "name": "Start IM minimized",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        },
        {
          "name": "Performance settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Thread priority",
              "description": "This setting may not have a noticeible impact on all platforms, especially higer end ones.",
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {
                "lowVal": 0,
                "highVal": 7,
                "interval": 1
              },
              "settingValue": 3,
              "settingType": 0,
              "settingControl": 2
            }
          ]
        }
      ],
      "settings": []
    },
    {
      "name": "Theme settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "Update settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "General settings",
      "description": null,
      "visible": true,
      "groups": [
        {
          "name": "Startup settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Start IM with Windows",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            },
            {
              "name": "Start IM minimized",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        },
        {
          "name": "Performance settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Thread priority",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": 3,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        }
      ],
      "settings": []
    },
    {
      "name": "Theme settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "Update settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    }
  ],
  "settings": []
}

您应该能够从中使用
KeyedListMergeConverter
(而不是专门用于合并
列表
集合的原始
KeyedListMergeConverter
),将
[JsonMergeKey]
附加到名称:

public class SettingGroup
{
    [JsonMergeKey]
    public string name { get; set; }
    // Remainder unchanged
}

public class Setting
{
    [JsonMergeKey]
    public string name { get; set; }
    // Remainder unchanged
}
然后像这样使用它:

        if (!Directory.Exists(Global.DataDirectory))
            Directory.CreateDirectory(Global.DataDirectory);
        var serializerSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Auto, ContractResolver = jsonResolver };
        serializerSettings.Converters.Add(new KeyedIListMergeConverter(settings.ContractResolver));
        JsonConvert.PopulateObject(File.ReadAllText(Path.Combine(Global.DataDirectory, fileName + ".json")), settingGroup, serializerSettings);

我认为为我的数据指定一个键可以解决我的问题,这是正确的吗@dbc添加了一些Json转储,以说明最终Json数据中的数据通知发生了什么,它应该是前两个的叠加结果,数据实际上是重复的,
性能设置
第二次出现时,
设置控件
属性本身设置为0。我无法重现您的问题。每次我使用您的
IgnorableSerializerContractResolver
往返您的
设置组
,结果都会原封不动地返回。看见您提到了一些关于“合并”的内容,因此,如果您能创建一个可复制的合并问题示例,我们可能会提供帮助。@dbc我不确定您想在这里演示什么,正如我所说的,设置文件保存并看起来与预期的一样,但当它合并回设置对象时,它会在其中创建重复项,因为据我所知,小提琴无法暂停执行,无法窥视设置对象以查看坏数据,所以这不会说明问题。在本例中,您可以看到合并的数据只是重复。啊,第一印象是,这工作非常出色!如果问题真的解决了,我会考虑一下,然后回来接受答案。
{
  "name": "Application Settings",
  "description": "Common application settings.",
  "visible": true,
  "groups": [
    {
      "name": "General settings",
      "description": null,
      "visible": true,
      "groups": [
        {
          "name": "Startup settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Start IM with Windows",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            },
            {
              "name": "Start IM minimized",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        },
        {
          "name": "Performance settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Thread priority",
              "description": "This setting may not have a noticeible impact on all platforms, especially higer end ones.",
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {
                "lowVal": 0,
                "highVal": 7,
                "interval": 1
              },
              "settingValue": 3,
              "settingType": 0,
              "settingControl": 2
            }
          ]
        }
      ],
      "settings": []
    },
    {
      "name": "Theme settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "Update settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "General settings",
      "description": null,
      "visible": true,
      "groups": [
        {
          "name": "Startup settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Start IM with Windows",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            },
            {
              "name": "Start IM minimized",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": true,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        },
        {
          "name": "Performance settings",
          "description": null,
          "visible": true,
          "groups": [],
          "settings": [
            {
              "name": "Thread priority",
              "description": null,
              "visible": true,
              "descriptionVisibility": 0,
              "configuration": {},
              "settingValue": 3,
              "settingType": 0,
              "settingControl": 0
            }
          ]
        }
      ],
      "settings": []
    },
    {
      "name": "Theme settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    },
    {
      "name": "Update settings",
      "description": null,
      "visible": true,
      "groups": [],
      "settings": []
    }
  ],
  "settings": []
}
public class SettingGroup
{
    [JsonMergeKey]
    public string name { get; set; }
    // Remainder unchanged
}

public class Setting
{
    [JsonMergeKey]
    public string name { get; set; }
    // Remainder unchanged
}
        if (!Directory.Exists(Global.DataDirectory))
            Directory.CreateDirectory(Global.DataDirectory);
        var serializerSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Auto, ContractResolver = jsonResolver };
        serializerSettings.Converters.Add(new KeyedIListMergeConverter(settings.ContractResolver));
        JsonConvert.PopulateObject(File.ReadAllText(Path.Combine(Global.DataDirectory, fileName + ".json")), settingGroup, serializerSettings);