U4-3782 - Propertyeditor datatype JSON

Created by Joachim Andersen 03 Dec 2013, 20:24:40 Updated by Kevin Giszewski 01 Jan 2014, 21:02:06

If I create a custom property type using the JSON valueType the value is stored in a Nvarchar where the maximum length is 500. I would expect that it was saved as an Ntext, or nvarchar(max).

Comments

Shannon Deminick 04 Dec 2013, 04:36:56

I cannot replicate this, JSON values are stored as Ntext. This is the code that checks in PropertyValueEditor:

/// <summary>
/// Returns the true DataTypeDatabaseType from the string representation ValueType
/// </summary>
/// <returns></returns>
public DataTypeDatabaseType GetDatabaseType()
{
    switch (ValueType.ToUpper())
    {
        case "INT":
        case "INTEGER":
            return DataTypeDatabaseType.Integer;
        case "STRING":
            return DataTypeDatabaseType.Nvarchar;
        case "TEXT":
        case "JSON":
        case "XML":
            return DataTypeDatabaseType.Ntext;
        case "DATETIME":
        case "DATE":
        case "TIME":
            return DataTypeDatabaseType.Date;
        default:
            throw new FormatException("The ValueType does not match a known value type");
    }
}

I've just tested this with a custom property editor of type JSON and it goes into the NText column in the db.


Joachim Andersen 04 Dec 2013, 05:59:38

OK, then it probably has to do with the fact that I started with valueType = STRING and then changed it to JSON later on. At least what happened was that I had to go to the data type table and change Nvarchar to Ntext (manually) in order to make it save my data (string or binary data would be truncated exception was thrown on save).

Should I open a new issue about this or (I mean changing valueType in the package.manifest file)??

Cheers Joachim


Shannon Deminick 04 Dec 2013, 06:02:17

Sure, if you open the issue please provide steps to replicate.


Joachim Andersen 04 Dec 2013, 10:37:43

After some more work I looked in the cmsDataType table in the database and noticed that all my data types were set to Nvarchar. This puzzled me so I looked in my package.manifest to confirm the valueTypes were set to what I remembered - and they were (I use both INT, TEXT, JSON and STRING). I then looked into the code to see where the valueType was read when building the propertyeditors from the manifest - The deserialize method looks like this (from PropertyEditorConverter.cs)

protected override void Deserialize(JObject jObject, PropertyEditor target, JsonSerializer serializer) { if (jObject["editor"] != null) { //since it's a manifest editor, we need to create it's instance. //we need to specify the view value for the editor here otherwise we'll get an exception. target.ManifestDefinedPropertyValueEditor = new PropertyValueEditor ;

            //the manifest JSON is a simplified json for the validators which is actually a dictionary, however, the
            //c# model requires an array of validators not a dictionary so we need to change the json to an array 
            //to deserialize properly.
            JArray converted;
            if (TryConvertValidatorDictionaryToArray(jObject["editor"]["validation"] as JObject, out converted))
            {
                jObject["editor"]["validation"] = converted;
            }

        }
        if (jObject["prevalues"] != null)
        {
            target.ManifestDefinedPreValueEditor = new PreValueEditor();

            //the manifest JSON is a simplified json for the validators which is actually a dictionary, however, the
            //c# model requires an array of validators not a dictionary so we need to change the json to an array 
            //to deserialize properly.
            var fields = jObject["prevalues"]["fields"] as JArray;
            if (fields != null)
            {
                foreach (var f in fields)
                {
                    JArray converted;
                    if (TryConvertValidatorDictionaryToArray(f["validation"] as JObject, out converted))
                    {
                        f["validation"] = converted;
                    }
                }
            }
        }

        base.Deserialize(jObject, target, serializer);
    }

The valueType is not read!

If I modify the method to the following:

    protected override void Deserialize(JObject jObject, PropertyEditor target, JsonSerializer serializer)
    {
        if (jObject["editor"] != null)
        {
            var valueType = jObject["valueType"] ?? "string";

            //since it's a manifest editor, we need to create it's instance.
            //we need to specify the view value for the editor here otherwise we'll get an exception.
            target.ManifestDefinedPropertyValueEditor = new PropertyValueEditor
                {
                    View = jObject["editor"]["view"].ToString(),
                    ValueType = valueType.ToString()
                };

            //the manifest JSON is a simplified json for the validators which is actually a dictionary, however, the
            //c# model requires an array of validators not a dictionary so we need to change the json to an array 
            //to deserialize properly.
            JArray converted;
            if (TryConvertValidatorDictionaryToArray(jObject["editor"]["validation"] as JObject, out converted))
            {
                jObject["editor"]["validation"] = converted;
            }

        }
        if (jObject["prevalues"] != null)
        {
            target.ManifestDefinedPreValueEditor = new PreValueEditor();

            //the manifest JSON is a simplified json for the validators which is actually a dictionary, however, the
            //c# model requires an array of validators not a dictionary so we need to change the json to an array 
            //to deserialize properly.
            var fields = jObject["prevalues"]["fields"] as JArray;
            if (fields != null)
            {
                foreach (var f in fields)
                {
                    JArray converted;
                    if (TryConvertValidatorDictionaryToArray(f["validation"] as JObject, out converted))
                    {
                        f["validation"] = converted;
                    }
                }
            }
        }

        base.Deserialize(jObject, target, serializer);
    }

I get the expected behaviour.

Can you reproduce that?


Shannon Deminick 05 Dec 2013, 01:39:35

Perhaps you are putting your valueType in the wrong place?

I've just noticed that the first example documentation is wrong - will update: http://umbraco.github.io/Belle/#/tutorials/manifest

But if you look further down, all of these fields:

hideLabel: true,
valueType: "TEXT",
validation: {},
isReadOnly: false 

belongs under the 'editor' item.


Kevin Giszewski 01 Jan 2014, 21:02:06

FYI, this totally helped me. I was getting the same issue until I realized the 'valueType' had to be set.

Cheers.


Priority: Normal

Type: Bug

State: Can't Reproduce

Assignee: Shannon Deminick

Difficulty: Normal

Category:

Backwards Compatible: True

Fix Submitted:

Affected versions: 7.0.0

Due in version: 7.0.1

Sprint:

Story Points:

Cycle: