Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.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# Net将结构序列化/反序列化为字符串_C#_Json_Struct_Json.net - Fatal编程技术网

C# Net将结构序列化/反序列化为字符串

C# Net将结构序列化/反序列化为字符串,c#,json,struct,json.net,C#,Json,Struct,Json.net,我有一个c#结构,用作字典键。为了使字典转换为json,我需要将struct序列化为string(就像json.net对内置结构所做的那样) 还有我的测试: var rating = new CreditRating { Level1 = "first", Level2 = "Sergey" }; var ratingJson = JsonConvert.SerializeObject(rating); // {"Level1":"first","Level2":

我有一个c#结构,用作字典键。为了使字典转换为json,我需要将struct序列化为string(就像json.net对内置结构所做的那样)

还有我的测试:

        var rating = new CreditRating { Level1 = "first", Level2 = "Sergey" };
        var ratingJson = JsonConvert.SerializeObject(rating); // {"Level1":"first","Level2":"Sergey","Level3":null}
        var rating2 = JsonConvert.DeserializeObject<CreditRating>(ratingJson);

        var dict = new Dictionary<CreditRating, double> {{rating, 2d}};
        var dictJson = JsonConvert.SerializeObject(dict); //{"first~Sergey~":2.0}
        var failingTest = JsonConvert.DeserializeObject<Dictionary<CreditRating, double>>(dictJson);
var评级=新的信用评级{Level1=“first”,Level2=“Sergey”};
var ratingJson=JsonConvert.SerializeObject(评级);//{“Level1”:“first”,“Level2”:“Sergey”,“Level3”:null}
var rating2=JsonConvert.DeserializeObject(ratingJson);
var dict=新字典{{rating,2d};
var dictJson=JsonConvert.SerializeObject(dict)//{“first~Sergey~”:2.0}
var failingTest=JsonConvert.DeserializeObject(dictJson);
最后一条语句失败,因为它没有调用我的解析方法或公共构造函数。
我按照文档进行了操作,但未能通过此操作。

好的,所以在尝试了很多东西之后,最终还是成功了-以防其他人遇到此问题:

[DataContract(Namespace = ContractNamespace.Current)]
public class CreditSpreadShiftWithLevels
{
    [OnDeserializing]
    private void Initialize(StreamingContext ctx)
    {
        ShiftsByRating = new Dictionary<CreditRating, double>();
    }
    [DataMember]
    public bool SplitByRating { get; set; }

    [DataMember]
    public double ShiftValue { get; set; }

    [DataMember]
    [JsonConverter(typeof(CreditRatingDoubleDictionaryConverter))]
    public Dictionary<CreditRating, double> ShiftsByRating { get; set; }

    //other properties

}

[DataContract(Namespace = ContractNamespace.Current)]
public struct CreditRating
{
    public CreditRating(string json): this()
    {
        var levels = json.Split(new[] { '~' }, StringSplitOptions.None);
        var cnt = levels.Length;
        if (cnt >= 3) Level3 = levels[2];
        if (cnt >= 2) Level2 = levels[1];
        if (cnt >= 1) Level1 = levels[0];
    }

    [DataMember]
    public string Level1 { get; set; }
    [DataMember]
    public string Level2 { get; set; }
    [DataMember]
    public string Level3 { get; set; }

    public override string ToString()
    {
        return string.Format("{0}~{1}~{2}", Level1, Level2, Level3);
    }
}


public class CreditRatingDoubleDictionaryConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var dict = new Dictionary<CreditRating, double>();
        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.PropertyName)
            {
                string readerValue = reader.Value.ToString();
                var cr = new CreditRating(readerValue);
                if (reader.Read() && reader.TokenType == JsonToken.Float)
                {
                    var val = Convert.ToDouble(reader.Value);
                    dict.Add(cr, val);
                }
            }
            if (reader.TokenType == JsonToken.EndObject) return dict;
        }
        return dict;
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(Dictionary<CreditRating, double>).IsAssignableFrom(objectType);
    }
}
[DataContract(Namespace=ContractNamespace.Current)]
公共类信用等级分为两级
{
[正在序列化]
私有void初始化(StreamingContext ctx)
{
ShiftsByRating=新字典();
}
[数据成员]
公共bool SplitByRating{get;set;}
[数据成员]
公共双移位值{get;set;}
[数据成员]
[JsonConverter(类型(CreditRatingDoubleDictionaryConverter))]
公共字典ShiftsByRating{get;set;}
//其他属性
}
[DataContract(Namespace=ContractNamespace.Current)]
公共结构信用评级
{
公共信用评级(字符串json):this()
{
var levels=json.Split(new[]{'~'},StringSplitOptions.None);
var cnt=水平。长度;
如果(cnt>=3)级别3=级别[2];
如果(cnt>=2)Level2=levels[1];
如果(cnt>=1)Level1=levels[0];
}
[数据成员]
公共字符串Level1{get;set;}
[数据成员]
公共字符串Level2{get;set;}
[数据成员]
公共字符串Level3{get;set;}
公共重写字符串ToString()
{
返回string.Format(“{0}{1}{2}”,Level1,Level2,Level3);
}
}
公共类CreditRatingDoubleDictionaryConverter:JsonConverter
{
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
serializer.Serialize(writer,value);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
var dict=新字典();
while(reader.Read())
{
if(reader.TokenType==JsonToken.PropertyName)
{
字符串readerValue=reader.Value.ToString();
var cr=新的信用评级(readerValue);
if(reader.Read()&&reader.TokenType==JsonToken.Float)
{
var val=Convert.ToDouble(reader.Value);
dict.Add(cr,val);
}
}
if(reader.TokenType==JsonToken.EndObject)返回dict;
}
返回命令;
}
公共覆盖布尔CanConvert(类型objectType)
{
返回typeof(Dictionary).IsAssignableFrom(objectType);
}
}
简而言之,我为字典(而不是struct)创建了转换器,它为我提供了父类的属性和属性。这使得在反序列化时json.net调用成为我的自定义逻辑。 库中已经内置了一些东西,在创建字典键时,可以将字典序列化调用到struct的ToString中(这使得它稍微不一致,因为它不尊重返回路径,即使文档有点建议-)

其中的一个难点是,我需要为每种不同类型的字典提供单独的转换器,这些字典使用struct作为其键,例如

public Dictionary<CreditRating, List<string>> BucketsByRating { get; set; }
公共字典BucketsByRating{get;set;}
需要另一个转换器。 我需要看看是否可以使用泛型来提高重用性,但如果我可以为struct提供一个转换器,该转换器将用于我拥有的所有不同的字典属性,那就更好了

无论如何,我希望这是有用的,可以节省一些时间


感谢所有提供建议的人,非常感谢您通常不应该使用
struct
。。。除非有特殊问题,否则应使用
class
。如果可以使用
Length
Structs,请尽量不要使用
Count()
,因为它总是有一个公共的无参数构造函数,这就是为什么Json.Net能够反序列化结构的原因。为什么您希望反序列化程序调用您的方法,为什么您需要它们?
级别
属性应已序列化请参见Json.NET和Dictionary的限制keys@PanagiotisKanavos我想他可能想使用自定义格式化程序进行序列化。。。将其序列化为
Level1~Level2~Level3
,而不是序列化属性。我可能应该补充一点,字典是另一个类的属性,如果这有任何区别的话
public Dictionary<CreditRating, List<string>> BucketsByRating { get; set; }