简体   繁体   中英

Trying to map two different types to one value

I have a DataMember that I need to be filled in by an api json string...

[DataContract]
public class Values
{
    [DataMember]
    public object value { get; set; }
}

API json string :

[
    {
        "type": "text",
        "values": [
            {
                "value": "Text that is in textfield"
            }
        ]
    },
    {
        "type": "category",
        "values": [
            {
                "value": {
                    "text": "Category title",
                    "color": "#000000"
                }
            }
        ]
    }
]

I map this string to a strong typed object Field like so:

    private List<Field> PrepFieldObject(string response)
    {
        using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(response)))
        {
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Field>));
            return (List<Field>)serializer.ReadObject(stream);
        }
    }

but when it gets to mapping Values.value , it throws a hissy fit... I tried solving it like this:

[DataContract]
public class Values
{
    [DataMember]
    public object value
    {
        get {
            return xamlValue;
        }
        set
        {                     
            xamlValue = new Value();

            if( value is string )
            {
                 xamlValue.text = (string)value; // This works fine
            }
            else
            {

                Value theValue = value as Value;
                try
                {
                    xamlValue.text = theValue.text; // Can't get hold of .text even though it does exist in the json.
                    xamlValue.color = theValue.color;
                }
                catch (Exception e)
                {
                }
            }
        }
    }
    public Value xamlValue { get; set; }
}

[DataContract]
public class Value
{
    [DataMember]
    public string text { get; set; }
    [DataMember]
    public string color { get; set; }
}

But it doesn't let me access properties of the object (I guess because they were never mapped by the DataContract)

I've tried adding

[KnownType(typeof(Value))]
[KnownType(typeof(string))]

but that doesn't help either :'(

您必须将其强制转换为text属性所属的任何类型。

((SomeType)value).text

You will have to use type-casting. Example string:

string abc = (string)value.text;

OR (preferably)

ComplexType comp = value as ComplexType;

UPDATE :

When you are trying to serialize a JSON object and convert it to a strongly-typed object (something my ComplexType is an example of), its important to have the same names for the properties as is in the JSON. After serialization, you should be able to access the property values.

Hope this helps!!!

You can just use the operator is , but you have to use it for each value that value can assume:

if (value is String)
{
    //do something
}
else if (value is ...)
...

You can read more about is here .

You COULD use a dynamic type:

DataContract]
public class Values
{
    [DataMember]
    public dynamic value { get; set; }
}

More about Dynamics

If you want a string or the defined string representation of the object use:

String valueAsString = value.ToString()

That is assuming that the other types (besides string) override the ToString() method to provide a meaningful string representation of the object.

Otherwise you would need to use:

KnownValueType kvt = value as KnownValueType
if(kvt!=null)
{
  //access known type properties here
}

I think you can use reflection to to access your object's property value. Try changing your setter's else part as

else
    {

        Value theValue = value as Value;
        try
        {   
            // pass the object and the property name you're trying to get hold of
            xamlValue.text = PropertyHasValue(theValue, "text"); // Can't get hold of .text even though it does exist in the json. 
            xamlValue.color = PropertyHasValue(theValue, "color");
        }
        catch (Exception e)
        {
        }
    }

And the reflection method

// using reflection to get the object's property value
public static String PropertyHasValue(object obj, string propertyName)
{
    try
    {
        if (obj != null)
        {
            PropertyInfo prop = obj.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
            if (prop != null)
            {
                string sVal = String.Empty;
                object val = prop.GetValue(obj, null);

                if (prop.PropertyType != typeof(System.DateTime?))
                    sVal = Convert.ToString(val);
                else // format the date to contain only the date portion of it
                    sVal = Convert.ToDateTime(val).Date.ToString("d"); ;

                if (sVal != null)
                {
                    return sVal;
                 }
             }
        }

        return null;
    }
    catch
    {
        return null;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM