3

I have a json object which I converted to dynamic C# object with help of this answer. It works just fine, but trouble is that this object has numerical keys. For instance,

var jsStr = "{address:{"100": {...}}}";  

So I can't wirte

dynObj.address.100  

And, as I know, I can't use indexers to get this object like this

dynObj.address["100"]  

Please explain to me how I can get this working.

Community
  • 1
  • 1
Tror
  • 442
  • 4
  • 12
  • Have you tried setting a breakpoint in visual studio, and inspect the dynamic object? – Yet Another Geek Jun 17 '11 at 14:54
  • @Cybernate I don't think this is a duplicate, as @Tror is asking how C#'s `dynamic` keyword can be used to access a property where the name of the property is not considered a valid identifier in C#. The question you referenced is specific to Javascript. – Donut Jun 17 '11 at 14:56
  • Cybernate, this is not a duplicate. His question is about javascript, but mine is about C# – Tror Jun 17 '11 at 14:58
  • Yet Another Geek, here is the [breakpoint window](http://clip2net.com/s/10go3) – Tror Jun 17 '11 at 15:02

3 Answers3

2

As far as I can see from the source code he resolves the properties through a private dictionary, so you have to use reflection to access the dictionary key, or modify his code a bit so that TryGetMember in DynamicJSONObject is the following (and use __numeric__ to get the key e.g. data.address.__numeric__100, and then avoid using __numeric__ as a key):

public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            var name = binder.Name; 
            //Code to check if key is of form __numeric__<number> so that numeric keys can be accessed
            if (binder != null && binder.Name != null && binder.Name.StartsWith("__numeric__"))
            {
                name = binder.Name.Substring(11);
            }

            if (!_dictionary.TryGetValue(name, out result))
            {
                // return null to avoid exception.  caller can check for null this way...
                result = null;
                return true;
            }

            var dictionary = result as IDictionary<string, object>;
            if (dictionary != null)
            {
                result = new DynamicJsonObject(dictionary);
                return true;
            }

            var arrayList = result as ArrayList;
            if (arrayList != null && arrayList.Count > 0)
            {
                if (arrayList[0] is IDictionary<string, object>)
                    result = new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)));
                else
                    result = new List<object>(arrayList.Cast<object>());
            }

            return true;
        }
Yet Another Geek
  • 4,251
  • 1
  • 28
  • 40
  • Thanks, I'll try it. At least it's better than nothing. I'd like to avoid such crap, but this is third-party service and I can do nothing with it. – Tror Jun 17 '11 at 21:41
  • It was just a patchy solution to a problem that was not though off in the original code. A better solution would have been something like Linq-to-XML type of access, but that required a lot of modification. – Yet Another Geek Jun 18 '11 at 08:19
1

My opensource framework ImpromptuInterface has methods to call dynamic members via string name of any C# 4 dynamic object.

object tOut =Impromptu.InvokeGet(dynObj.address,"100");

I tested it with an ExpandoObject it seemed to work just fine.

jbtule
  • 31,383
  • 12
  • 95
  • 128
0

An identifier must start with a letter, underscore (_), or dollar sign ($); subsequent characters can also be digits (0-9). Because JavaScript is case sensitive, letters include the characters "A" through "Z" (uppercase) and the characters "a" through "z" (lowercase). Starting with JavaScript 1.5, ISO 8859-1 or Unicode letters (or \uXXXX Unicode escape sequences) can be used in identifiers.

Quoted from: http://en.wikipedia.org/wiki/JavaScript_syntax#Variables

Oh I am sorry mis understood the question, well here you go with a working example you can adjust to your needs:

<script>
var jsStr = {address:{'100': 'test'}};
var test = jsStr.address;
console.log(test);
alert(test[100]);        
</script>

btw key CAN be numeric (as you see in the example in the answer), only the identifiers cannot. so you have to access just like you tried. you only have to leave away the quotes for numeric keys! and your json string will not be an object without evaluation, so in this example its strictly speaking a javascript object and not json but it doesnt matter to t he subject

The Surrican
  • 29,118
  • 24
  • 122
  • 168