public void JsonLeaf(string propertyName, string value, bool isQuoted) { if (objectTypePending) { bool isTypeSpecifierLeaf = false; Type attributeTypeHint = null; if (propertyName.Equals(TypeSpecifier)) { attributeTypeHint = TypeAntiAliaser(value); isTypeSpecifierLeaf = true; } else { attributeTypeHint = inferCurrentTypeFromStack(false); } if (attributeTypeHint == null) { string message = String.Format("cant load type: \"{0}\" in json:{1}", value, json); NoClueForTypeException ex = new NoClueForTypeException(message); throw ex; } object newObject = newInstance(attributeTypeHint); ObjectFrame objectHolder = (ObjectFrame)objects.Peek(); objectHolder.theObject = newObject; listener.onCreateObject(newObject); objectTypePending = false; if (isTypeSpecifierLeaf) { return; } } if (objectTypePending || objects.Count == 0) { string message = string.Format("unable to set property {0} with value {1} because type is not found yet ", propertyName, value); throw new Exception(message); } string strError = null; if (TypeSpecifier != null && propertyName != null && propertyName.Equals(TypeSpecifier)) { // todo raise a warning here or throw an exception in strict mode } else { objects.Peek().submitLeafToStack(propertyName, value, setValueinObject, listener); } if (strError != null) { throw new Exception(strError); } }
Type inferCurrentTypeFromStack(bool autocreate) { if (this.objects.Count == 0) { return(null); } Type currentType = null; Type parentType = null; for (int done = (this.objects.Count - 1); done >= 0; done--) { parentType = currentType; currentType = null; ObjectFrame oFrame = this.objects.ElementAt(done) as ObjectFrame; ArrayFrame aFrame = this.objects.ElementAt(done) as ArrayFrame; string propertyName = null; if (oFrame != null) { currentType = oFrame.theObject != null?oFrame.theObject.GetType() : null; propertyName = oFrame.propertyName; } if (aFrame != null) { propertyName = aFrame.propertyName; } if (currentType == null && parentType != null) { //infer from the parentType and propertyName if (propertyName != null) { PropertyInfo pi = parentType.GetProperty(propertyName); if (pi != null) { currentType = pi.PropertyType; } } else if (parentType.IsGenericType) { Type[] gtypes = parentType.GetGenericArguments(); if (gtypes != null && gtypes.Length == 1) { currentType = gtypes[0]; } } } if (autocreate && currentType != null && oFrame != null && oFrame.theObject == null) { oFrame.theObject = newInstance(currentType); } } return(currentType); }
public void JsonEndObject(int pos) { if (objectTypePending) { if (objects.Count() > 0) { ObjectFrame currentFrame = objects.Peek() as ObjectFrame; if (currentFrame != null && currentFrame.theObject == null) { //fix parent chain Type inferredType = inferCurrentTypeFromStack(true); if (inferredType != null) { objectTypePending = false; } } } if (objectTypePending) { string strMessage = String.Format("unable to determine type of object terminated at pos {0} in {1}", pos, json); throw new NoClueForTypeException(strMessage); } } if (objects.Count < 1) { string strMessage = String.Format("too many object terminations at pos {0} in {1}", pos, json); throw new OverTerminatedObjectException(strMessage); } lastObject = objects.Pop(); ObjectFrame lastFrame = lastObject as ObjectFrame; if (lastFrame == null) { throw new UnterminatedObjectException("unexpected non Object frame " + lastFrame.GetType().Name); } listener.onEndObject(lastFrame.theObject); if (objects.Count() > 0) { objects.Peek().submitObjectToStack(((ObjectFrame)lastObject).propertyName, ((ObjectFrame)lastObject).theObject, setValueinObject, listener); } }
public void JsonStartObject(string propertyName, int pos) { // if the typeHint is not null create theobject // otherwise defer until a class attribute property is available //todo restruct typeHint usage based on whetherits thetop object ObjectFrame objectHolder = new ObjectFrame(); objectHolder.propertyName = propertyName; objects.Push(objectHolder); if (typeHint != null) { object newObject = newInstance(typeHint); objectHolder.theObject = newObject; listener.onCreateObject(newObject); objectTypePending = false; typeHint = null; return; } objectTypePending = true; }