web-dev-qa-db-ja.com

デフォルトのプライベートコンストラクターを持つクラスのC#オブジェクトにjsonを逆シリアル化します

次のクラスのためにjsonを逆シリアル化する必要があります。

public class Test
{
    public string Property { get; set; }

    private Test()
    {
        //NOTHING TO INITIALIZE
    }

    public Test(string prop)
    {
        Property = prop;
    }
}

私は次のようなテストのインスタンスを作成できます

var instance = new Test("Instance");

私のjsonを次のようなものと考えています

"{  "Property":"Instance" }"

デフォルトのコンストラクターがプライベートであり、プロパティがNULLであるオブジェクトを取得しているため、Testクラスのオブジェクトを作成するにはどうすればよいですか?

NewtonsoftJsonパーサーを使用しています。

17
Shantanu Gupta

[JsonConstructor]属性でマークすることにより、Json.Netにプライベートコンストラクターを呼び出させることができます。

[JsonConstructor]
private Test()
{
    //NOTHING TO INITIALIZE
}

シリアライザーは、コンストラクターを呼び出した後も、パブリックセッターを使用してオブジェクトにデータを入力することに注意してください。

[〜#〜]編集[〜#〜]

別の可能なオプションは、ConstructorHandling設定を使用することです。

JsonSerializerSettings settings = new JsonSerializerSettings
{
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};

Test t = JsonConvert.DeserializeObject<Test>(json, settings);
37
Brian Rogers

追加の手順を実行する必要はないようです。

Json.NET v6.0.8を使用すると、次のC#プログラムがLINQPad内で機能します。

void Main()
{   
    var o = JsonConvert.DeserializeObject<Test>("{\"Property\":\"Instance\"}");

    Debug.Assert(o.Property == "Instance",
        "Property value not set when deserializing.");
}

public class Test
{
    public string Property { get; set; }

    private Test()
    {
    }

    public Test(string propertyValue)
    {
        Property = propertyValue;
    }
}
2
Dave Watts

ここでSerializer設定を作成し、assignConstructorHandlingを指定する必要はありません。プライベートコンストラクターに[JsonConstructor]属性を定義することを忘れないでください。抽象BaseNode.csとその具体的なComputerNode.cs実装についても同様のケースがあります。クラスを作成し、以下のコードをコピーして貼り付け、いくつかの実験を行うことができます。

    public abstract class BaseNode
{
    [JsonConstructor] // ctor used when Json Deserializing
    protected BaseNode(string Owner, string Name, string Identifier)
    {
        this.Name = Name;
        this.Identifier = Identifier;
    }

    // ctor called by concrete class.
    protected BaseNode(string [] specifications)
    {
        if (specifications == null)
        {
            throw new ArgumentNullException();
        }
        if (specifications.Length == 0)
        {
            throw new ArgumentException();
        }

        Name = specifications[0];
        Identifier = specifications[1];

    }

    public string Name{ get; protected set; }
    public string Identifier { get; protected set; }

}


public class ComputerNode: BaseNode
{
    public string Owner { get; private set; }

    [JsonConstructor] // not visible while creating object from outside and only used during Json Deserialization.
    private ComputerNode(string Owner, string Name, string Identifier):base(Owner, Name, Identifier)
    {
        this.Owner = Owner;
    }

    public ComputerNode(string[] specifications):base(specifications)
    {
        Owner = specifications[2];
    }
}

JSonの読み取りと書き込みの場合、次のコードが役立ちます-

    public class Operation<T>
{
    public string path;

    public Operation()
    {
        var path = Path.Combine(Directory.GetCurrentDirectory(), "nodes.txt");

        if (File.Exists(path) == false)
        {
            using (File.Create(path))
            {
            }
        }
        this.path = path;
    }

    public void Write(string path, List<T> nodes)
    {
        var ser = JsonConvert.SerializeObject(nodes, Formatting.Indented);

        File.WriteAllText(path, ser);
    }

    public List<T> Read(string path)
    {
        var text = File.ReadAllText(path);

        var res =  JsonConvert.DeserializeObject<List<T>>(text);
        return res;
    }

}

最高です!

1
jack_t