[英]JSON.NET Deserializer is returning Null
编辑:它与 try/catch return null 语句无关。 我已经调试并观看了它并确保它不会进入那个 catch 块。 我什至评论了它,但无济于事。
我很累为我的应用程序构建配置管理器。 本质上,我有某些变量需要存储在 JSON 文件中并在应用程序启动期间读取,以便知道某些值。
对于其中一些配置变量,我将允许用户覆盖默认值,因此如果“用户”键具有非空字符串,我将使用它。 如果没有用户密钥或有空字符串,我将使用默认值。 为了满足这个要求,我编写了“AllowUserConfig”和“CoalesceUserDefault”方法来解决这个问题。
此时,我有一个 JSON 文件(如下)。 我复制了数据并作为一个类 JSONConfig 粘贴到 Visual Studio 中。 然后我有一个 ConfigManager 文件来完成真正的工作,我的 program.cs 调用 ConfigManager 以使用 DeserializeConfigVariables 方法读取配置文件(位于正确的位置),并从中创建一个 JSONConfig 对象。
话虽如此, DeserializeConfigVariables 中的 JSONConfig 对象将作为 null 返回(在configVariables = serializer.Deserialize<JSONConfig>(jsonReader);
)。 有什么我想念的吗。 我已经把每件事都翻了一百遍,但看不出我做错了什么。
任何和所有帮助将不胜感激。
这是我的 JSON:
{
"format": {
"date": {
"default": "yyyyMMdd",
"user": ""
},
"month_year": {
"default": "MM_YYYY",
"user": ""
}
},
"placeholders": {
"current_date": "{date}",
"month_year": "{month_year}",
"last_monday": "{prev_monday}",
"next_monday": "{next_monday}"
},
"resource_locations": {
"directories": {
"root_working": {
"default": "C:\\ALL",
"user": ""
},
"exports": {
"default": "C:\\ALL\\Exports",
"user": ""
},
"completed_exports": {
"default": "C:\\ALL\\Done",
"user": ""
},
"archived": {
"default": "C:\\ALL\\Archives",
"user": ""
}
},
"compression": {
"filename": {
"default": "{next_monday}_daily_{date}.zip",
"user": ""
}
},
"logging": {
"directory": "logs",
"process_filename": "activity_log_{month_year}.log",
"process_error_filename": "errors.log",
"system_error_filename": "sys_errors.log"
}
}
}
这是我通过在 Visual Studio 中复制和粘贴 JSON 作为类创建的 JSONConfig 类:
using System;
using Newtonsoft.Json;
namespace Config
{
public class JSONConfig
{
public RootObject ConfigVariables { get; set; }
}
public class RootObject
{
public Format format { get; set; }
public Placeholders placeholders { get; set; }
public Resource_Locations resource_locations { get; set; }
}
public class Format
{
public Date date { get; set; }
public Month_Year month_year { get; set; }
}
public class Date
{
public string _default { get; set; }
public string user { get; set; }
}
public class Month_Year
{
public string _default { get; set; }
public string user { get; set; }
}
public class Placeholders
{
public string current_date { get; set; }
public string month_year { get; set; }
public string last_monday { get; set; }
public string next_monday { get; set; }
}
public class Resource_Locations
{
public Directories directories { get; set; }
public Compression compression { get; set; }
public Logging logging { get; set; }
}
public class Directories
{
public Root_Working root_working { get; set; }
public Exports exports { get; set; }
public Completed_Exports completed_exports { get; set; }
public Archived archived { get; set; }
}
public class Root_Working
{
public string _default { get; set; }
public string user { get; set; }
}
public class Exports
{
public string _default { get; set; }
public string user { get; set; }
}
public class Completed_Exports
{
public string _default { get; set; }
public string user { get; set; }
}
public class Archived
{
public string _default { get; set; }
public string user { get; set; }
}
public class Compression
{
public Filename filename { get; set; }
}
public class Filename
{
public string _default { get; set; }
public string user { get; set; }
}
public class Logging
{
public string directory { get; set; }
public string process_filename { get; set; }
public string process_error_filename { get; set; }
public string system_error_filename { get; set; }
}
}
然后,在我的 ConfigManager 文件中,我有以下内容:
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
using Newtonsoft.Json;
namespace Config
{
static class ConfigManager
{
// Assumes parent directory is bin. Assumes config is sibling to bin.
private static string _initialConfig = @"config\config.json";
public static string ConfigPath() => Path.Combine(GetRootAppDir(), _initialConfig);
public static string Parent(string directory)
{
string parentDirectory = Directory.GetParent(directory).FullName;
return parentDirectory;
}
public static string GetRootAppDir()
{
return Parent(Parent(Directory.GetCurrentDirectory()));
}
public static JSONConfig DeserializeConfigVariables()
{
try
{
var configVariables = new JSONConfig();
var serializer = new JsonSerializer();
Console.WriteLine($"Config Path: {ConfigPath()}"); //testing
using (var reader = new StreamReader(ConfigPath()))
using (var jsonReader = new JsonTextReader(reader))
{
configVariables = serializer.Deserialize<JSONConfig>(jsonReader);
}
return configVariables;
}
catch (System.IO.DirectoryNotFoundException ex)
{
Console.WriteLine(ex.Message);
return null;
}
}
public static bool AllowUserConfig(object configVariable)
{
string userFieldName = "user";
var objType = configVariable.GetType();
return objType.GetMethod(userFieldName) != null;
}
public static string CoalesceUserDefault(dynamic configVariable)
{
if (AllowUserConfig(configVariable))
{
if (!(String.IsNullOrEmpty(configVariable.user)))
{
return configVariable.user;
}
}
return configVariable._default;
}
}
}
您的 Json 不包含根中名为ConfigVariable
的属性,如类JSONConfig
定义的JSONConfig
(您尝试反序列化的类型)。
如果您检查,Json 符合RootObject
的定义。 你应该反序列化类RootObject.You的实例,可以把它分配给ConfigVariable
的实例的属性JsonConfig
如果你的目的是将配置保存在JsonConfig的实例。
configVariables.ConfigVariables = serializer.Deserialize<RootObject>(jsonReader);
希望,对你有帮助。
您可以添加yourjsonfile.json
文件,例如:-
yourjsonfile.json
{
"key1": "value1",
"key2": "value2",
"ConnectionStrings": {
"$ref": "anotherjsonfile.json#"
}
}
另一个jsonfile.json
{
"key2": "value4"
}
确保您的jsonfile.json 和anotherjsonfile.json 文件属性将“复制到输出目录”设置为“始终复制”。
从yourjsonfile.json
和 anotherjsonfile.json 文件中查找值, yourjsonfile.json
所示 -
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
IConfiguration configuration = builder.Build();
string GetValue1 = configuration.GetSection("key1").Value;
string GetValue2 = configuration.GetSection("key2").Value;
var builder1 = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(configuration.GetConnectionString("$ref").Replace("#", ""), optional: true, reloadOnChange: true);
IConfiguration configuration1 = builder1.Build();
GetValue2 = (configuration1.GetSection("key2").Value) != null ? configuration1.GetSection("key2").Value : GetValue2;
谢谢!!!
您需要将 json 反序列化为RootObject
,而不是JSONConfig
configVariables = serializer.Deserialize<RootObject>(jsonReader);
您的 json 具有三个根对象, Format
、 Placeholders
和ResourceLocations
……但是您用来将 json 反序列化为的类只有一个对象……并且不匹配。
您可以随时使用 www.json2csharp.com,将您的 json 粘贴到那里,然后查看您需要反序列化到哪个对象(base 始终是 RootObject 那里)。
如何使用 JSONConfig 类
如果你真的想使用 JSONConfig 来反序列化你的 json,那么你需要稍微修改一下你的 JSON。 您需要将另一个根元素ConfigVariables
添加到 json。
{ "ConfigVariables" :
{
"format": {
"date": {
"default": "yyyyMMdd",
"user": ""
...
推荐
将反序列化 JSON 的方法也更改为更简单的过程。
public static RootObject DeserializeConfigVariables()
{
return JsonConvert.DeserializeObject<RootObject>(File.ReadAllLines(ConfigPath()));
}
您的 Json 文件与您用来反实现它的对象结构不对应。 您的JsonConfig
文件包含ConfigVariables
属性,但 json 文件包含format
、 placeholders
、 resource_locations
属性, ConfigVariables
属性应该在第二级。 尝试通过以下方式更新您的配置文件:
{
"ConfigVariables": {
"format": {
"date": {
"default": "yyyyMMdd",
"user": ""
},
"month_year": {
"default": "MM_YYYY",
"user": ""
}
},
"placeholders": {
"current_date": "{date}",
"month_year": "{month_year}",
"last_monday": "{prev_monday}",
"next_monday": "{next_monday}"
},
"resource_locations": {
"directories": {
"root_working": {
"default": "C:\\ALL",
"user": ""
},
"exports": {
"default": "C:\\ALL\\Exports",
"user": ""
},
"completed_exports": {
"default": "C:\\ALL\\Done",
"user": ""
},
"archived": {
"default": "C:\\ALL\\Archives",
"user": ""
}
},
"compression": {
"filename": {
"default": "{next_monday}_daily_{date}.zip",
"user": ""
}
},
"logging": {
"directory": "logs",
"process_filename": "activity_log_{month_year}.log",
"process_error_filename": "errors.log",
"system_error_filename": "sys_errors.log"
}
}
}
}
它会解决你的问题。 顺便说一句,正如我所见,您在配置对象中以 json 样式命名了属性。 例如, resource_locations
最好以常规方式命名属性并添加JsonProperty
属性以进行正确映射。 例如
[JsonProperty('resource_locations')]
public ResourceLocations ResouceLocations { get; set; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.