【问题标题】:How to deserialize a string into a class?如何将字符串反序列化为类?
【发布时间】:2012-12-04 17:41:03
【问题描述】:

我有以下文字:

id=1
familyName=Rooney
givenName=Wayne
middleNames=Mark
dateOfBirth=1985-10-24
dateOfDeath=
placeOfBirth=Liverpool
height=1.76
twitterId=@WayneRooney

行用“\n”隔开,对用“=”隔开。

我有一个 Person 类,其中包含 Id、FamilyName、GivenName 等属性。

是否有任何简单的方法可以将上述文本反序列化为 Person 对象,然后使用正确的行和对分隔符将 Person 对象序列化为上述文本?

我希望有类似 TextSerializer 的东西?

基本上,我需要从文件中读取文本,例如person1.txt 然后将其反序列化为 Person 对象。

如果可能,我想避免为每个属性手动硬编码。 谢谢,

【问题讨论】:

  • 那么,您正在尝试从文件中读取文本并将其存储在对象“FamilyInfo”或其他对象的数组中?
  • 我从文件中读取文本,例如person1.txt 然后需要将其反序列化为 Person 对象。
  • 文件中的每个Person 实例是用什么分隔的,还是每个文件只有一个?
  • 这种格式类似于INI。您可能可以欺骗Nini 为您完成这项工作,但您必须问“这是按合同工作还是巧合?”我可能会自己编写代码;这不是很多工作。

标签: c# asp.net xml serialization text


【解决方案1】:

反射可以在这里提供帮助,无需硬编码属性名称和使用第三方库

var person = Deserialize<Person2>("a.txt");

T Deserialize<T>(string fileName)
{
    Type type = typeof(T);
    var obj = Activator.CreateInstance(type);
    foreach (var line in File.ReadLines(fileName))
    {
        var keyVal = line.Split('=');
        if (keyVal.Length != 2) continue;

        var prop = type.GetProperty(keyVal[0].Trim());
        if (prop != null)
        {
            prop.SetValue(obj, Convert.ChangeType(keyVal[1], prop.PropertyType));
        }
    }
    return (T)obj;
}

public class Person2
{
    public int id { set; get; }
    public string familyName { set; get; }
    public string givenName { set; get; }
    public string middleNames { set; get; }
    public string dateOfBirth { set; get; }
    public string dateOfDeath { set; get; }
    public string placeOfBirth { set; get; }
    public double height { set; get; }
    public string twitterId { set; get; }
}

【讨论】:

  • 使用反射将是一种有趣的方法。 CustomPersonSerializer
  • @TheLight 实际上它可以用于反序列化任何对象(Deserialize&lt;AntType&gt;),因此我不会在名称中使用Person。也许PrimitiveSerializer
  • 你能传递一个接口而不是一个具体的类吗?它在 Activator.CreateInstance(type) 行上失败。如何从接口创建对象?
  • @TheLight 假设您可以传递一个接口,您认为代码应该如何找到实现该接口的具体类(无法创建接口的实例)。出于同样的原因,其他内置序列化程序也不接受接口。
  • @TheLight 还假设我添加了代码来搜索所有程序集以查找实现该接口的类型。如果有两个类实现了这个接口怎么办。应该创建哪一个?
【解决方案2】:

这也是一个可能的解决方案。 如果可能,您可以尝试在创建时将文本格式化为 json。 所以你不需要所有这些治疗。只需使用Json.net

public class Person
{
    public int id { set; get; }
    public string familyName { set; get; }
    public string givenName { set; get; }
    public string middleNames { set; get; }
    public string dateOfBirth { set; get; }
    public string dateOfDeath { set; get; }
    public string placeOfBirth { set; get; }
    public double height { set; get; }
    public string twitterId { set; get; }
}

class Program
{
    static void Main(string[] args)
    {
        string line;
        string newText = "{";

        System.IO.StreamReader file =  new System.IO.StreamReader("c:\\test.txt");

        while ((line = file.ReadLine()) != null)
        {
            newText += line.Insert(line.IndexOf("=") + 1, "\"") + "\",";

        }
        file.Close();

        newText = newText.Remove(newText.Length -1);
        newText = newText.Replace("=", ":");
        newText += "}";


        Person Person = JsonConvert.DeserializeObject<Person>(newText);

        Console.ReadLine();
    }
}

希望对您有所帮助。

【讨论】:

  • 这很有趣,您首先将其转换为 JSON 格式,这是一种更简单的序列化方法。
【解决方案3】:

正如其他人提到的,您有多种选择:

  1. 加载文件,将其转换为可与 XMLSerializer/DataContract 一起使用的 XML
  2. 使用 IFormatter 编写您自己的序列化程序
  3. 通过读取文件手动执行(示例如下)

    类人 { 公共 int ID { 获取;放; } 公共字符串 FamilyName { 获取;放; }

    public Person(string file)
    {
        if (!File.Exists(file))
            return;
    
        string[] personData = File.ReadAllLines(file);
    
        foreach (var item in personData)
        {
            string[] itemPair = item.Split('='); //do some error checking here to see if = isn't appearing twice
            string itemKey = itemPair[0];
            string itemValue = itemPair[1];
            switch (itemKey)
            {
                case "familyName":
                    this.FamilyName = itemValue;
                    break;
                case "id":
                    this.ID = int.Parse(itemValue);
                    break;
                default:
                    break;
            }
    
        }
    }
    

    }

【讨论】:

  • 我在格式化代码的第一行时遇到问题,但您明白了要点。
  • I'd like to avoid hardcoding it manually for each property if possible
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-08
  • 2022-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-20
相关资源
最近更新 更多