日本語版
最新ニュース
企業

効率的な方法でプロパティから JSON データを取得する

私の中で 最後の投稿 組み込みの PropertyList タイプに対する小さな調整について書きました。今回は、何度も繰り返される JSON 逆シリアル化を置き換えることができる、あまり知られていないトリックを紹介します。非常に多くの Web サイト ソリューションでそれが発生するのを見てきたので、私は知っています。 場合によっては、コンテンツ モデル クラスに簡単に適切に保存できない複雑なデータを保存する必要があります。これは、PIM システムからの大きな製品データである可能性があります。 CMS ページ上のイベントに関する複雑なデータである可能性があります。あるいは、ページ上にさまざまなフィールドが多数必要な場合や、コンテンツ アイテムの深い階層が必要な場合、あるいは単に JSON 文字列として保存したい場合もあります。私はこれを判断するつもりはありません。 これは次のように簡単です。 public record ComplexDataObject{public string Key { get; set; }public string Color { get; set; }public Dictionary Data {…

1772184896
2026-02-23 06:00:00

私の中で 最後の投稿 組み込みの PropertyList タイプに対する小さな調整について書きました。今回は、何度も繰り返される JSON 逆シリアル化を置き換えることができる、あまり知られていないトリックを紹介します。非常に多くの Web サイト ソリューションでそれが発生するのを見てきたので、私は知っています。

場合によっては、コンテンツ モデル クラスに簡単に適切に保存できない複雑なデータを保存する必要があります。これは、PIM システムからの大きな製品データである可能性があります。 CMS ページ上のイベントに関する複雑なデータである可能性があります。あるいは、ページ上にさまざまなフィールドが多数必要な場合や、コンテンツ アイテムの深い階層が必要な場合、あるいは単に JSON 文字列として保存したい場合もあります。私はこれを判断するつもりはありません。

これは次のように簡単です。

public record ComplexDataObject
{
public string Key { get; set; }
public string Color { get; set; }
public Dictionary Data { get; set; }
}

public class ArticlePage : PageData
{
public string RawJsonData { get; set; }
}

次に、次のようにコントローラーでそれを逆シリアル化できます。

var complexDataObject = JsonSerializer.Deserialize(currentContent.RawJsonData);

しかし、これは賢明なのでしょうか? JSON 文字列はいつデシリアライズされますか?

あらゆるリクエストに応じて。 これはレンダリングのパフォーマンスに良くありません。

解決

代わりに、JSON が最初の使用時にのみ (親コンテンツがキャッシュから削除されるまで) 遅延的に逆シリアル化されることを保証する、あまり知られていない方法を利用できます。

JSON をオブジェクトに逆シリアル化する独自のプロパティ型を作成することで、事前にシリアル化または逆シリアル化することなく、型指定されたオブジェクトを取得してプロパティに設定できます。

[PropertyDefinitionTypePlugIn]
// Use this line in Commerce Connect.
// public class PropertyComplexDataObject : PropertyLongString, ILazyProperty
public class PropertyComplexDataObject: PropertyJson, ILazyProperty {
    private ComplexDataObject _complexDataObject = null;
    private Func _lazyValueFactory;

    public override Type PropertyValueType => typeof (ComplexDataObject);

    public virtual ComplexDataObject Data {
        get => _complexDataObject;
        set {
            ThrowIfReadOnly();
            if (value == null) {
                ClearNoCheck();
            }

            if (_complexDataObject.Equals(value)) {
                return;
            }

            // Check whether the object is actually different from the existing.
            _lazyValueFactory = null;
            _complexDataObject = value;
            ModifiedNoCheck();
        }
    }

    public override object Value {
        get => Data;
        set {
            ThrowIfReadOnly();
            SetPropertyValue(value, delegate {
                _complexDataObject = value as ComplexDataObject;
            });
        }
    }

    public override void ParseToSelf(string value) {
        ThrowIfReadOnly();
        if (string.IsNullOrWhiteSpace(value)) {
            ClearNoCheck();
            return;
        }

        Data = JsonSerializer.Deserialize  (value);
    }

    // In Commerce Connect, uncomment this line.
    // public override object SaveData(PropertyDataCollection properties) => JsonSerializer.Serialize(Data);

    public override bool IsNull => _lazyValueFactory == null && _complexDataObject == null;

    protected override void SetDefaultValue() {
        _complexDataObject = null;
        _lazyValueFactory = null;
    }

    private void ClearNoCheck() {
        if (IsNull) {
            return;
        }

        ModifiedNoCheck();
        SetDefaultValue();
    }

    bool ILazyProperty.HasLazyValue => _lazyValueFactory != null;

    void ILazyProperty.AssignValueFactory(Func  valueFactory) {
        ThrowIfReadOnly();
        if (IsNull && valueFactory != null) {
            ModifiedNoCheck();
        }

        _complexDataObject = null;

        if (_lazyValueFactory != valueFactory) {
            _lazyValueFactory = valueFactory;
            ModifiedNoCheck();
        }
    }
}

次に、次のように ArticlePage のプロパティを変更できます。

 public class ArticlePage : PageData
{
    [BackingType(typeof(PropertyComplexDataObject))]
    [CultureSpecific]
    [Editable(false)]
    [UIHint(UIHint.Textarea)]
    public virtual ComplexDataObject RawProductData { get; set; }
} 

これは、JSON プロパティの遅延読み込みのサポートが組み込まれているため、CMS では正常に機能します。 Commerce Connect の場合は、JSON のネイティブ MetaDataType がないため、いくつかの調整が必要です。したがって、コードのコメントに示されているように、LongString に戻ります。

ボーナスチップ

で述べたように、 以前のブログ投稿、IsModified フラグに注意する必要があります。この場合は少し難しくなります。ただし、カスタム Equals メソッドを使用してそれを行う 1 つの方法があります。

public record ComplexDataObject
{
    public string Key { get; set; }
    public string Color { get; set; }
    public Dictionary Data { get; set; }
 
    // Even though records come with an Equals method, we override this to check the dictionary for equality.
    public bool Equals(ComplexDataObject x, ComplexDataObject y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (x is null || y is null) return false;
        if (!string.Equals(x.Key, y.Key, StringComparison.Ordinal)) return false;
        if (!string.Equals(x.Color, y.Color, StringComparison.Ordinal)) return false;
        if (x.Data.Count != y.Data.Count) return false;
 
        foreach (var kvp in x.Data)
            if (!y.Data.TryGetValue(kvp.Key, out var value) ||
                !string.Equals(value, kvp.Value, StringComparison.Ordinal))
                return false;
 
        return true;
    }
} 

#効率的な方法でプロパティから #JSON #データを取得する

執筆者について: nipponese

Nipponese News編集部は、国内外のニュースを日本語で分かりやすくお届けします。