Example #1
0
 internal void ResolveValue(JsonPlusValue child)
 {
     if (child.Count == 0)
     {
         Remove(child);
     }
 }
Example #2
0
        /// <summary>
        /// Parses the Json+ source code specified into structured objects.
        /// </summary>
        /// <param name="source">The source code that conforms to Json+ specification.</param>
        /// <param name="includeCallback">Callback used to resolve the `include` directive.</param>
        /// <param name="resolveSubstitutions">Resolve substitution directives.</param>
        /// <param name="resolveEnv">Try to resolve environment variables. Does nothing if <paramref name="resolveSubstitutions"/> is `false`.</param>
        /// <returns></returns>
        private JsonPlusRoot ParseSource(string source, bool resolveSubstitutions, bool resolveEnv, IncludeCallbackAsync includeCallback)
        {
            if (string.IsNullOrWhiteSpace(source))
            {
                throw new JsonPlusParserException(string.Format(RS.SourceEmptyError, nameof(source)));
            }

            if (includeCallback != null)
            {
                _includeCallback = includeCallback;
            }

            try
            {
                _tokens = new JPlusTokenizer(source).Tokenize();
                _root   = new JsonPlusValue(null);
                ParseTokens();
                if (resolveSubstitutions)
                {
                    ResolveAllSubstitution(resolveEnv);
                }
            }
            catch (JsonPlusTokenizerException e)
            {
                throw JsonPlusParserException.Create(e, null, string.Format(RS.TokenizeError, e.Message), e);
            }
            catch (JsonPlusException e)
            {
                throw JsonPlusParserException.Create(_tokens.Current, Path, e.Message, e);
            }

            return(new JsonPlusRoot(_root, _substitutions));
        }
Example #3
0
        private JsonPlusValue ResolveSubstitution(JsonPlusSubstitution sub)
        {
            JsonPlusObjectMember subField = sub.ParentMember;

            // first case, this substitution is a direct self-reference
            if (sub.Path == sub.GetMemberPath())
            {
                IJsonPlusNode parent = sub.Parent;
                while (parent is JsonPlusValue)
                {
                    parent = parent.Parent;
                }

                // Fail case
                if (parent is JsonPlusArray)
                {
                    throw new JsonPlusException(RS.SelfRefSubstitutionInArray);
                }

                // try to resolve substitution by looking backward in the field assignment stack
                return(subField.OlderValueThan(sub));
            }

            // need to recursively get full path
            JsonPlusPath fieldPath = subField.GetMemberPath();

            // second case, the substitution references a field child in the past
            if (sub.Path.IsChildPathOf(fieldPath))
            {
                JsonPlusValue olderValue = subField.OlderValueThan(sub);
                if ((olderValue != null) &&
                    (olderValue.Type == JsonPlusType.Object))
                {
                    int          difLength = sub.Path.Count - fieldPath.Count;
                    JsonPlusPath deltaPath = sub.Path.SubPath(sub.Path.Count - difLength, difLength);

                    JsonPlusObject olderObject = olderValue.GetObject();
                    if (olderObject.TryGetValue(deltaPath, out JsonPlusValue innerValue))
                    {
                        return(innerValue.Type == JsonPlusType.Object ? innerValue : null);
                    }
                }
            }

            // Detect invalid parent-referencing substitution
            if (fieldPath.IsChildPathOf(sub.Path))
            {
                throw new JsonPlusException(RS.SubstitutionRefDirectParentError);
            }

            // Detect invalid cyclic reference loop
            if (IsValueCyclic(subField, sub))
            {
                throw new JsonPlusException(RS.CyclicSubstitutionLoop);
            }

            // third case, regular substitution
            _root.GetObject().TryGetValue(sub.Path, out JsonPlusValue field);
            return(field);
        }
Example #4
0
        internal void ResolveValue(JsonPlusValue value)
        {
            if (value.Type != JsonPlusType.Empty)
            {
                return;
            }

            ((JsonPlusObject)Parent).ResolveValue(this);
        }
Example #5
0
        /// <summary>
        /// Returns a node as a <see cref="Nullable{Int64}"/> object by parsing the value as a number with data size unit.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <returns>The <see cref="Nullable{Int64}"/> value of the node specified by <paramref name="path"/>.</returns>
        /// <see cref="JsonPlusValue.GetByteSize()"/>
        public long?GetByteSize(JsonPlusPath path)
        {
            JsonPlusValue value = GetNode(path);

            if (ReferenceEquals(value, JsonPlusValue.Undefined))
            {
                return(null);
            }
            return(value.GetByteSize());
        }
Example #6
0
        /// <see cref="IJsonPlusNode.Clone(IJsonPlusNode)"/>
        public virtual IJsonPlusNode Clone(IJsonPlusNode newParent)
        {
            JsonPlusValue clone = new JsonPlusValue(newParent);

            foreach (IJsonPlusNode value in this)
            {
                clone.Add(value.Clone(clone));
            }
            return(clone);
        }
Example #7
0
        /// <summary>
        /// Returns a node as a <see cref="decimal"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <param name="defaultValue">The default value to return if the node specified by <paramref name="path"/> does not exist. Defaults to zero.</param>
        /// <returns>The <see cref="decimal"/> value of the node specified by <paramref name="path"/>, or <paramref name="defaultValue"/> if the node does not exist.</returns>
        public decimal GetDecimal(JsonPlusPath path, decimal defaultValue = 0)
        {
            JsonPlusValue value = GetNode(path);

            if (ReferenceEquals(value, JsonPlusValue.Undefined))
            {
                return(defaultValue);
            }

            return(value.GetDecimal());
        }
Example #8
0
        /// <summary>
        /// Returns a node as an <see cref="long"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <param name="defaultValue">The default value to return if the node specified by <paramref name="path"/> does not exist. Defaults to zero.</param>
        /// <returns>The <see cref="Int64"/> value of the node specified by <paramref name="path"/>, or <paramref name="defaultValue"/> if the node does not exist.</returns>
        public long GetInt64(JsonPlusPath path, long defaultValue = 0)
        {
            JsonPlusValue value = GetNode(path);

            if (ReferenceEquals(value, JsonPlusValue.Undefined))
            {
                return(defaultValue);
            }

            return(value.GetInt64());
        }
Example #9
0
        /// <summary>
        /// Returns a node as an <see cref="int"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <param name="defaultValue">The default value to return if the node specified by <paramref name="path"/> does not exist. Defaults to zero.</param>
        /// <returns>The <see cref="Int32"/> value of the node specified by <paramref name="path"/>, or <paramref name="defaultValue"/> if the node does not exist.</returns>
        public int GetInt32(JsonPlusPath path, int defaultValue = 0)
        {
            JsonPlusValue value = GetNode(path);

            if (ReferenceEquals(value, JsonPlusValue.Undefined))
            {
                return(defaultValue);
            }

            return(value.GetInt32());
        }
Example #10
0
        /// <summary>
        /// Return a node as a <see cref="bool"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <param name="defaultValue">The default value to return if the node specified by <paramref name="path"/> does not exist.</param>
        /// <returns>The <see cref="bool"/> value of the node specified by <paramref name="path"/>, or <paramref name="defaultValue"/> if the node does not exist.</returns>
        public bool GetBoolean(JsonPlusPath path, bool defaultValue = false)
        {
            JsonPlusValue value = GetNode(path);

            if (ReferenceEquals(value, JsonPlusValue.Undefined))
            {
                return(defaultValue);
            }

            return(value.GetBoolean());
        }
Example #11
0
        /// <summary>
        /// Returns a node as a <see cref="double"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <param name="defaultValue">The default value to return if the node specified by <paramref name="path"/> does not exist. Defaults to zero.</param>
        /// <returns>The <see cref="double"/> value of the node specified by <paramref name="path"/>, or <paramref name="defaultValue"/> if the node does not exist.</returns>
        public double GetDouble(JsonPlusPath path, double defaultValue = 0)
        {
            JsonPlusValue value = GetNode(path);

            if (ReferenceEquals(value, JsonPlusValue.Undefined))
            {
                return(defaultValue);
            }

            return(value.GetDouble());
        }
Example #12
0
        /// <summary>
        /// Returns a node as an enumerable collection <see cref="string"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <exception cref="JsonPlusParserException">The node cannot be casted into an array.</exception>
        /// <returns>The <see cref="IList{String}"/> value of the node specified by <paramref name="path"/>.</returns>
        public IList <string> GetStringList(JsonPlusPath path)
        {
            JsonPlusValue value = GetNode(path);

            if (ReferenceEquals(value, JsonPlusValue.Undefined))
            {
                throw new JsonPlusParserException(string.Format(RS.ErrCastNodeByPathToArray, path));
            }

            return(value.GetStringList());
        }
Example #13
0
        /// <summary>
        /// Returns a node as a <see cref="TimeSpan"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <param name="defaultValue">The default value to return if the node specified by <paramref name="path"/> does not exist. Defaults to `null`.</param>
        /// <param name="allowInfinite">Set to `true` to allow the keyword `infinite`. Otherwise, `false`. Defaults to `true`.</param>
        /// <returns>The <see cref="TimeSpan"/> value of the node specified by <paramref name="path"/>, or <paramref name="defaultValue"/> if the node does not exist.</returns>
        public TimeSpan GetTimeSpan(JsonPlusPath path, TimeSpan?defaultValue = null, bool allowInfinite = true)
        {
            JsonPlusValue value = GetNode(path);

            if (value == null)
            {
                return(defaultValue.GetValueOrDefault());
            }

            return(value.GetTimeSpan(allowInfinite));
        }
Example #14
0
        /// <summary>
        /// Returns a node as a <see cref="float"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <param name="defaultValue">The default value to return if the node specified by <paramref name="path"/> does not exist. Defaults to zero.</param>
        /// <returns>The <see cref="float"/> value of the node specified by <paramref name="path"/>, or <paramref name="defaultValue"/> if the node does not exist.</returns>
        public float GetSingle(JsonPlusPath path, float defaultValue = 0)
        {
            JsonPlusValue value = GetNode(path);

            if (ReferenceEquals(value, JsonPlusValue.Undefined))
            {
                return(defaultValue);
            }

            return(value.GetSingle());
        }
Example #15
0
        /// <summary>
        /// Returns the backing <see cref="JsonPlusValue"/> value of the <see cref="JsonPlusObjectMember"/> associated with
        /// the <see cref="JsonPlusPath"/> specified. The path is relative to the this instance.
        /// </summary>
        /// <param name="path">The relative <see cref="JsonPlusPath"/> path associated with the <see cref="JsonPlusObjectMember"/> of the <see cref="JsonPlusValue"/>.</param>
        /// <param name="result">If the field is returned successfully, this parameter will contain the backing <see cref="JsonPlusValue"/> of the <see cref="JsonPlusObjectMember"/> associated
        /// with <paramref name="path"/> (if the path is resolvable). This parameter should be passed uninitialized.</param>
        /// <returns>`true` if the <see cref="JsonPlusObject"/> contains the <see cref="JsonPlusObjectMember"/> resolvable by the <paramref name="path"/> specified. Otherwise, `false`.</returns>
        public bool TryGetValue(JsonPlusPath path, out JsonPlusValue result)
        {
            result = null;

            if (!TryGetMember(path, out JsonPlusObjectMember field))
            {
                return(false);
            }

            result = field.Value;
            return(true);
        }
Example #16
0
        internal void EnsureMemberIsObject()
        {
            if (Type == JsonPlusType.Object)
            {
                return;
            }

            JsonPlusValue  v = new JsonPlusValue(this);
            JsonPlusObject o = new JsonPlusObject(v);

            v.Add(o);
            _internalValues.Add(v);
        }
Example #17
0
        private JsonPlusObjectMember ParseObjectMember(JsonPlusObject owner)
        {
            // sanity check
            if (_tokens.Current.Type != TokenType.LiteralValue)
            {
                throw JsonPlusParserException.Create(_tokens.Current, Path, string.Format(RS.UnexpectedTokenInMember, TokenType.LiteralValue, _tokens.Current.Type));
            }

            JsonPlusPath pathDelta = ParseKey();

            if (_tokens.Current.IsNonSignificant())
            {
                ConsumeWhitelines();
            }

            // sanity check
            if (_tokens.Current.Type != TokenType.Assignment &&
                _tokens.Current.Type != TokenType.StartOfObject &&
                _tokens.Current.Type != TokenType.SelfAssignment)
            {
                throw JsonPlusParserException.Create(_tokens.Current, Path,
                                                     string.Format(RS.UnexpectedTokenWith3AltInMember,
                                                                   TokenType.Assignment, TokenType.StartOfObject, TokenType.SelfAssignment,
                                                                   _tokens.Current.Type));
            }

            // sanity check
            if (pathDelta == null || pathDelta.Count == 0)
            {
                throw JsonPlusParserException.Create(_tokens.Current, Path, RS.ObjectMemberPathUnspecified);
            }

            List <JsonPlusObjectMember> childInPath = owner.TraversePath(pathDelta);

            Path.AddRange(pathDelta);
            JsonPlusObjectMember currentField = childInPath[childInPath.Count - 1];

            JsonPlusValue parsedValue = ParseValue(currentField);

            foreach (JsonPlusSubstitution removedSub in currentField.SetValue(parsedValue))
            {
                _substitutions.Remove(removedSub);
            }

            Path.RemoveRange(Path.Count - pathDelta.Count, pathDelta.Count);
            return(childInPath[0]);
        }
Example #18
0
        internal JsonPlusValue OlderValueThan(IJsonPlusNode marker)
        {
            List <JsonPlusObject> objectList = new List <JsonPlusObject>();
            int index = 0;

            while (index < _internalValues.Count)
            {
                JsonPlusValue value = _internalValues[index];
                if (value.Any(v => ReferenceEquals(v, marker)))
                {
                    break;
                }

                switch (value.Type)
                {
                case JsonPlusType.Object:
                    objectList.Add(value.GetObject());
                    break;

                case JsonPlusType.Literal:
                case JsonPlusType.Array:
                    objectList.Clear();
                    break;
                }

                index++;
            }

            if (objectList.Count == 0)
            {
                return(index == 0
                    ? null
                    : _internalValues[index - 1]);
            }

            JsonPlusValue  result = new JsonPlusValue(null);
            JsonPlusObject o      = new JsonPlusObject(result);

            result.Add(o);

            foreach (JsonPlusObject obj in objectList)
            {
                o.Merge(obj);
            }

            return(result);
        }
Example #19
0
        internal List <JsonPlusSubstitution> SetValue(JsonPlusValue value)
        {
            List <JsonPlusSubstitution> removedSubs = new List <JsonPlusSubstitution>();

            if (value.Type == JsonPlusType.Array || value.Type == JsonPlusType.Literal)
            {
                List <JsonPlusSubstitution> subs = value.GetAllSubstitution();
                if (subs.All(sub => sub.Path != Path))
                {
                    foreach (JsonPlusValue item in _internalValues)
                    {
                        removedSubs.AddRange(item.GetAllSubstitution());
                    }
                    _internalValues.Clear();
                }
            }
            _internalValues.Add(value);
            return(removedSubs);
        }
Example #20
0
 /// <summary>
 /// Returns a value indicating whether the value of this instance is equal to the value of the specified <see cref="JsonPlusValue"/> instance.
 /// </summary>
 /// <param name="other">The object to compare to this instance.</param>
 /// <returns>
 /// `true` if the <paramref name="other"/> parameter equals the value of this instance. Otherwise, `false`.
 /// </returns>
 protected bool Equals(JsonPlusValue other)
 {
     return(Type == other.Type && GetString() == other.GetString());
 }
Example #21
0
        private bool IsValueCyclic(JsonPlusObjectMember field, JsonPlusSubstitution sub)
        {
            Stack <JsonPlusValue>       pendingValues = new Stack <JsonPlusValue>();
            List <JsonPlusObjectMember> visitedFields = new List <JsonPlusObjectMember> {
                field
            };
            Stack <JsonPlusSubstitution> pendingSubs = new Stack <JsonPlusSubstitution>();

            pendingSubs.Push(sub);

            while (pendingSubs.Count > 0)
            {
                JsonPlusSubstitution currentSub = pendingSubs.Pop();
                if (!_root.GetObject().TryGetMember(currentSub.Path, out var currentField))
                {
                    continue;
                }

                if (visitedFields.Contains(currentField))
                {
                    return(true);
                }

                visitedFields.Add(currentField);
                pendingValues.Push(currentField.Value);
                while (pendingValues.Count > 0)
                {
                    JsonPlusValue currentValue = pendingValues.Pop();

                    foreach (IJsonPlusNode value in currentValue)
                    {
                        switch (value)
                        {
                        case JsonPlusLiteralValue _:
                            break;

                        case JsonPlusObject o:
                            foreach (JsonPlusObjectMember f in o.Values)
                            {
                                if (visitedFields.Contains(f))
                                {
                                    return(true);
                                }

                                visitedFields.Add(f);
                                pendingValues.Push(f.Value);
                            }
                            break;

                        case JsonPlusArray a:
                            foreach (JsonPlusValue item in a.GetArray())
                            {
                                pendingValues.Push(item);
                            }
                            break;

                        case JsonPlusSubstitution s:
                            pendingSubs.Push(s);
                            break;
                        }
                    }
                }
            }
            return(false);
        }
Example #22
0
 static JsonPlusValue()
 {
     Undefined = new EmptyValue(null);
 }
Example #23
0
        /// <summary>
        /// Returns the underlying <see cref="JsonPlusLiteralType"/> of a literal value.
        /// </summary>
        /// <exception cref="JsonPlusException">The <see cref="Type"/> property must be of type <see cref="JsonPlusType.Literal"/>.</exception>
        /// <returns>
        /// The underlying <see cref="JsonPlusLiteralType"/> of an instance of this <see cref="JsonPlusValue"/> which is a literal value.
        /// </returns>
        public virtual JsonPlusLiteralType GetLiteralType()
        {
            if (Type != JsonPlusType.Literal)
            {
                throw new JsonPlusException(RS.ExpectLiteralType);
            }

            if (Count > 1)
            {
                bool containsSubstitution = false;
                foreach (IJsonPlusNode node in Children)
                {
                    if (node is JsonPlusSubstitution)
                    {
                        containsSubstitution = true;
                        break;
                    }
                }

                if (containsSubstitution)
                {
                    return(JsonPlusLiteralType.String);
                }

                if (IsTimeSpan())
                {
                    return(JsonPlusLiteralType.TimeSpan);
                }

                if (IsByteSize())
                {
                    return(JsonPlusLiteralType.ByteSize);
                }

                return(JsonPlusLiteralType.String);
            }

            if (Count == 0)
            {
                return(JsonPlusLiteralType.Null);
            }

            // timespan and bytesize expressions will have at least 2 children, so here onwards node cannot be either.
            IJsonPlusNode firstChild = Children[0];

            if (firstChild is JsonPlusSubstitution)
            {
                JsonPlusValue substChild = ((JsonPlusSubstitution)firstChild).ResolvedValue;
                if (substChild.Type != JsonPlusType.Literal)
                {
                    throw new JsonPlusException(string.Format(RS.InternalErrorStopCode, "ONLY_SUBST_TYPE_NOT_LITERAL"));
                }

                return(substChild.GetLiteralType());
            }

            if (firstChild is NullValue)
            {
                return(JsonPlusLiteralType.Null);
            }
            else if (firstChild is BooleanValue)
            {
                return(JsonPlusLiteralType.Boolean);
            }
            else if (firstChild is DecimalValue)
            {
                return(JsonPlusLiteralType.Decimal);
            }
            else if (firstChild is IntegerValue)
            {
                return(JsonPlusLiteralType.Integer);
            }
            else if (firstChild is HexadecimalValue)
            {
                return(JsonPlusLiteralType.Hexadecimal);
            }
            else if (firstChild is OctetValue)
            {
                return(JsonPlusLiteralType.Octet);
            }
            else if (firstChild is UnquotedStringValue)
            {
                return(JsonPlusLiteralType.UnquotedString);
            }
            else if (firstChild is QuotedStringValue)
            {
                return(JsonPlusLiteralType.QuotedString);
            }
            else if (firstChild is TripleQuotedStringValue)
            {
                return(JsonPlusLiteralType.TripleQuotedString);
            }
            else if (firstChild is WhitespaceValue)
            {
                return(JsonPlusLiteralType.Whitespace);
            }
            else
            {
                throw new JsonPlusException(string.Format(RS.UnknownLiteralToken, firstChild.GetType().ToString()));
            }
        }
Example #24
0
        /// <summary>
        /// Retrieves the next value token from the tokenizer and appends it
        /// to the supplied element <paramref name="owner"/>.
        /// </summary>
        /// <param name="owner">The element to append the next token.</param>
        /// <exception cref="Exception">End of file reached while trying to read a value</exception>
        private JsonPlusValue ParseValue(IJsonPlusNode owner)
        {
            JsonPlusValue value   = new JsonPlusValue(owner);
            bool          parsing = true;

            while (parsing)
            {
                switch (_tokens.Current.Type)
                {
                case TokenType.Include:
                case TokenType.OptionalInclude:
                    value.Add(ParseInclude(value));
                    break;

                case TokenType.LiteralValue:
                    // Consume leading whitespaces.
                    if (_tokens.Current.IsNonSignificant())
                    {
                        ConsumeWhitespace();
                    }
                    if (_tokens.Current.Type != TokenType.LiteralValue)
                    {
                        break;
                    }

                    while (_tokens.Current.Type == TokenType.LiteralValue)
                    {
                        value.Add(JsonPlusLiteralValue.Create(value, _tokens.Current));
                        _tokens.Next();
                    }
                    break;

                case TokenType.StartOfObject:
                    value.Add(ParseObject(value));
                    break;

                case TokenType.StartOfArray:
                    value.Add(ParseArray(value));
                    break;

                case TokenType.OptionalSubstitution:
                case TokenType.Substitution:
                    JsonPlusPath         pointerPath = JsonPlusPath.Parse(_tokens.Current.Value);
                    JsonPlusSubstitution sub         = new JsonPlusSubstitution(value, pointerPath, _tokens.Current,
                                                                                _tokens.Current.Type == TokenType.Substitution);
                    _substitutions.Add(sub);
                    value.Add(sub);
                    _tokens.Next();
                    break;

                case TokenType.EndOfObject:
                case TokenType.EndOfArray:
                    parsing = false;
                    break;

                // comments automatically stop value parsing.
                case TokenType.Comment:
                    ConsumeWhitelines();
                    parsing = false;
                    break;

                case TokenType.EndOfLine:
                    parsing = false;
                    break;

                case TokenType.EndOfFile:
                case TokenType.ArraySeparator:
                    parsing = false;
                    break;

                case TokenType.SelfAssignment:
                    JsonPlusSubstitution subAssign = new JsonPlusSubstitution(value, new JsonPlusPath(Path), _tokens.Current, false);
                    _substitutions.Add(subAssign);
                    value.Add(subAssign);

                    value.Add(ParseSelfAssignArray(value));
                    parsing = false;
                    break;

                case TokenType.Assignment:
                    ConsumeWhitelines();
                    break;

                default:
                    throw JsonPlusParserException.Create(_tokens.Current, Path, string.Format(RS.ErrAtUnexpectedToken, _tokens.Current.Type));
                }
            }

            // trim trailing whitespace if result is a literal
            if (value.Type == JsonPlusType.Literal)
            {
                if (value[value.Count - 1] is WhitespaceValue)
                {
                    value.RemoveAt(value.Count - 1);
                }
            }
            return(value);
        }
Example #25
0
        /// <summary>
        /// Returns a node as a generic <see cref="JsonPlusValue"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <returns>The <see cref="JsonPlusValue"/> value of the node specified by <paramref name="path"/>, or `null` if the node does not exist.</returns>
        public JsonPlusValue GetValue(JsonPlusPath path)
        {
            JsonPlusValue value = GetNode(path);

            return(value);
        }
Example #26
0
        private void ResolveAllSubstitution(bool resolveEnv)
        {
            foreach (JsonPlusSubstitution sub in _substitutions)
            {
                // Retrieve value
                JsonPlusValue res;
                try
                {
                    res = ResolveSubstitution(sub);
                }
                catch (JsonPlusException e)
                {
                    throw JsonPlusParserException.Create(sub, sub.Path, string.Format(RS.SubstitutionError, e.Message), e);
                }

                if (res != null)
                {
                    sub.ResolvedValue = res;
                    continue;
                }

                if (resolveEnv)
                {
                    // Try to pull value from environment
                    string envValue = null;
                    try
                    {
                        envValue = Environment.GetEnvironmentVariable(sub.Path.Value);
                    }
                    catch (Exception)
                    {
                        // ignored
                    }

                    if (envValue != null)
                    {
                        // undefined value resolved to an environment variable
                        res = new JsonPlusValue(sub.Parent);
                        if (envValue.NeedQuotes())
                        {
                            res.Add(new QuotedStringValue(sub.Parent, envValue));
                        }
                        else
                        {
                            res.Add(new UnquotedStringValue(sub.Parent, envValue));
                        }

                        sub.ResolvedValue = res;
                        continue;
                    }
                }

                // ${ throws exception if it is not resolved
                if (sub.Required)
                {
                    throw JsonPlusParserException.Create(sub, sub.Path, string.Format(RS.UnresolvedSubstitution, sub.Path));
                }

                sub.ResolvedValue = new EmptyValue(sub.Parent);
            }
        }
Example #27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JsonPlusRoot"/> class.
 /// </summary>
 /// <param name="value">The value to associate with this instance.</param>
 /// <param name="substitutions">An enumeration of substitutions to associate with this instance.</param>
 public JsonPlusRoot(JsonPlusValue value, IEnumerable <JsonPlusSubstitution> substitutions)
 {
     Value         = value;
     Substitutions = substitutions;
 }
Example #28
0
        /// <summary>
        /// Returns a node as a <see cref="string"/>.
        /// </summary>
        /// <param name="path">A Json+ query path that identifies a node in the current context.</param>
        /// <param name="defaultValue">The default value to return if the node specified by <paramref name="path"/> does not exist. Defaults to `null`.</param>
        /// <returns>The <see cref="string"/> value of the node specified by <paramref name="path"/>, or <paramref name="defaultValue"/> if the node does not exist.</returns>
        public string GetString(JsonPlusPath path, string defaultValue = null)
        {
            JsonPlusValue value = GetNode(path);

            return(ReferenceEquals(value, JsonPlusValue.Undefined) ? defaultValue : value.GetString());
        }
Example #29
0
 /// <summary>
 /// Initializes a new instance of the <see cref="JsonPlusRoot"/> class.
 /// </summary>
 /// <param name="value">The value to associate with this node.</param>
 public JsonPlusRoot(JsonPlusValue value)
     : this(value, Enumerable.Empty <JsonPlusSubstitution>())
 {
 }