如何在 .NET 中将空字符串反序列化为 long?

How to handle deserialization of empty string into long in .NET?

下图表示在 Serialization/Deserialization.

的帮助下使用 TestClass1 类型的对象构建 TestClass2 类型的对象

TestClass1TestClass2 具有相同的结构,只是其中一个成员在 TestClass1 中是 string 而在 TestClass2 中是 long。

public class TestClass1
{
    public string strlong;
}

public class TestClass2
{
    public long strlong;
}

TestClass1 objT1 = new TestClass1();
objT1.strlong = "20134567";
TestClass2 objT2;
JavaScriptSerializer serializer = new JavaScriptSerializer();
string JSON1 = serializer.Serialize(objT1);
objT2 = serializer.Deserialize<TestClass2>(JSON1);

操作后,objT2 将具有 objT1 的值,但 strlong 现在将是长而不是字符串。

问题是,如果 objT1 中的 strlong 值为空字符串 --> "",反序列化失败并出现异常 "" is not a valid value for Int64

如果 strlong 是仅包含数字字符的非空字符串,则当前反序列化有效。但是当出现空字符串之类的东西时,我不知道解决方法。

现在,让我们假设

  1. strlong 将在 long
  2. 的范围内
  3. 将只是一个数字字符序列,即它不会有 .,/ 或任何类型的其他字符
  4. 只能访问用于序列化的对象,我无法修改 TestClass1TestClass2

如果有一种简单的方法(或没有)使用另一个 class 的对象创建一个 class 的对象,请在评论中提及。

编辑-扩展逻辑

为了将下面的答案中给出的解决方案逻辑扩展到 类 包含类型为其他 class 的成员,我也对成员项目使用了下面给出的序列化解决方案。换句话说,如果 classes 包含其他 classes 的成员,是否有比下面的代码更好的处理更深层次的方法?

// **Item1 :** 
// These are the subclasses and classes
// whose objects I am trying to serialize
// and deserialize from one type to another
public class SubClass1
{
    public string toomuch;
    public int number = 30;
}

public class SubClass2
{
    public long toomuch;
    public int number;
}

public class TestClass1
{
    public string strlong;
    public SubClass1 item2;
}

public class TestClass2
{
    public long strlong;
    public SubClass2 item2;
}

// **Item2 :** 
// Solution from Whosebug for serialization of 
// empty string
public class TestClass1Converter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(TestClass1) }; }
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        var data = obj as TestClass1;
        var dic = new Dictionary<string, object>();
        if (data == null)
        {
            return dic;
        }

        long val = 0;
        long.TryParse(data.strlong, out val);
        dic.Add("strlong", val);

        // **Item3 :** 
        // trying to serialize and deserialize item2 which is of type SubClass1
        // which might also have empty string
        /*******************/
        JavaScriptSerializer subClassSerializer = new JavaScriptSerializer();
        subClassSerializer.RegisterConverters(new[] { new SubClass1Converter() });
        string JSONstr = subClassSerializer.Serialize(data.item2);
        dic.Add("item2", subClassSerializer.Deserialize<SubClass2>(JSONstr));
        /*******************/

        return dic;
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

// **Item4 :** 
// Serialization for subclass
public class SubClass1Converter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(SubClass1) }; }
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        var data = obj as SubClass1;
        var dic = new Dictionary<string, object>();
        if (data == null)
        {
            return dic;
        }

        long val = 0;
        long.TryParse(data.toomuch, out val);
        dic.Add("toomuch", val);
        dic.Add("number", data.number);
        return dic;
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

class Program
{
    static void Main(string[] args)
    {
        TestClass1 objT1 = new TestClass1();
        objT1.strlong = "";
        SubClass1 objSub = new SubClass1();
        objSub.toomuch = "";
        objT1.item2 = objSub;
        TestClass2 objT2;


        JavaScriptSerializer serializer = new JavaScriptSerializer();
        serializer.RegisterConverters(new[] { new TestClass1Converter() });
        string JSON1 = serializer.Serialize(objT1);
        objT2 = serializer.Deserialize<TestClass2>(JSON1);
    }
}

您应该将 TestClass2.strlong 声明为可为空。

public class TestClass2
{
    public long? strlong;
}

现在您可以使用 null 以防 TestClass1.strlong 为空字符串或 null。

这是 UPDATE,以防您无法修改 类。

您应该通过 RegisterConverters 将转换器添加到序列化程序以自定义转换。这是示例:

public class TestClass1Converter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new Type[] { typeof(TestClass1)}; }
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        var data = obj as TestClass1;
        var dic = new Dictionary<string, object>();
        if(data == null)
        {
            return dic;
        }

        long val = 0;
        long.TryParse(data.strlong, out val);
        dic.Add("strlong", val);
        return dic;
    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

此转换器会将 strlong 序列化为 0,以防无法转换为 long。你可以这样使用它:

TestClass1 objT1 = new TestClass1();
objT1.strlong = "444";
TestClass2 objT2;
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new [] {new TestClass1Converter()});
string JSON1 = serializer.Serialize(objT1);
objT2 = serializer.Deserialize<TestClass2>(JSON1);