/// <summary>
        /// Generates a JSON Pointer from a lambda expression.
        /// </summary>
        /// <typeparam name="T">The type of the object.</typeparam>
        /// <param name="expression">The lambda expression which gives the pointer path.</param>
        /// <returns>The JSON Pointer.</returns>
        /// <exception cref="NotSupportedException">
        /// Thrown when the lambda expression contains a node that is not a property access or
        /// <see cref="int"/>-valued indexer.
        /// </exception>
        public static JsonPointer Create <T>(Expression <Func <T, object> > expression)
        {
            var body     = expression.Body;
            var segments = new List <PointerSegment>();

            while (body != null)
            {
                if (body.NodeType == ExpressionType.Convert && body is UnaryExpression unary)
                {
                    body = unary.Operand;
                }

                if (body is MemberExpression me)
                {
                    segments.Insert(0, PointerSegment.Create(me.Member.Name));
                    body = me.Expression;
                }
                else if (body is MethodCallExpression mce &&
                         mce.Method.Name.StartsWith("get_") &&
                         mce.Arguments.Count == 1 &&
                         mce.Arguments[0].Type == typeof(int))
                {
                    segments.Insert(0, PointerSegment.Create(mce.Arguments[0].ToString()));
                    body = mce.Object;
                }
Example #2
0
        /// <summary>
        /// Concatenates additional segments onto the current pointer.
        /// </summary>
        /// <param name="additionalSegments">The additional segments.</param>
        /// <returns>A new pointer.</returns>
        public JsonPointer Combine(params PointerSegment[] additionalSegments)
        {
            var segments = new PointerSegment[Segments.Length + additionalSegments.Length];

            Segments.CopyTo(segments, 0);
            additionalSegments.CopyTo(segments, Segments.Length);

            return(new JsonPointer
            {
                Segments = segments,
                Kind = IsUriEncoded ? JsonPointerKind.UriEncoded : JsonPointerKind.Plain
            });
        }
Example #3
0
        /// <summary>
        /// Concatenates a pointer onto the current pointer.
        /// </summary>
        /// <param name="other">Another pointer.</param>
        /// <returns>A new pointer.</returns>
        public JsonPointer Combine(JsonPointer other)
        {
            var segments = new PointerSegment[Segments.Length + other.Segments.Length];

            Segments.CopyTo(segments, 0);
            other.Segments.CopyTo(segments, Segments.Length);

            return(new JsonPointer
            {
                Segments = segments,
                Kind = IsUriEncoded ? JsonPointerKind.UriEncoded : JsonPointerKind.Plain
            });
        }
        /// <summary>
        /// Parses a JSON Pointer from a string.
        /// </summary>
        /// <param name="source">The source string.</param>
        /// <param name="pointerKind">(optional) Restricts the kind of pointer.  <see cref="JsonPointerKind.Unspecified"/> (default) allows both.</param>
        /// <returns>A JSON Pointer.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        /// <exception cref="PointerParseException"><paramref name="source"/> does not contain a valid pointer or contains a pointer of the wrong kind.</exception>
        public static JsonPointer Parse(string source, JsonPointerKind pointerKind = JsonPointerKind.Unspecified)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (source == string.Empty)
            {
                return(Empty);
            }
            if (source == "#")
            {
                return(UrlEmpty);
            }

            bool isUriEncoded;
            var  parts = source.Split('/');
            var  i     = 0;

            if (parts[0] == "#" || parts[0] == string.Empty)
            {
                isUriEncoded = parts[0] == "#";
                i++;
            }
            else
            {
                throw new PointerParseException("Pointer must start with either `#` or `/` or be empty");
            }

            switch (pointerKind)
            {
            case JsonPointerKind.Unspecified:
                break;

            case JsonPointerKind.Plain:
                if (isUriEncoded)
                {
                    throw new PointerParseException("Pointer is URI-encoded, but plain was expected.");
                }
                break;

            case JsonPointerKind.UriEncoded:
                if (!isUriEncoded)
                {
                    throw new PointerParseException("Pointer is plain, but URI-encoded was expected.");
                }
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(pointerKind), pointerKind, null);
            }

            var segments = new PointerSegment[parts.Length - i];

            for (; i < parts.Length; i++)
            {
                segments[i - 1] = PointerSegment.Parse(parts[i], isUriEncoded);
            }

            return(new JsonPointer
            {
                _source = source,
                _segments = segments,
                Kind = isUriEncoded ? JsonPointerKind.UriEncoded : JsonPointerKind.Plain
            });
        }
        /// <summary>
        /// Parses a JSON Pointer from a string.
        /// </summary>
        /// <param name="source">The source string.</param>
        /// <param name="pointer">The resulting pointer.</param>
        /// <param name="pointerKind">(optional) Restricts the kind of pointer.  <see cref="JsonPointerKind.Unspecified"/> (default) allows both.</param>
        /// <returns><code>true</code> if the parse was successful; <code>false</code> otherwise.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        public static bool TryParse(string source, out JsonPointer pointer, JsonPointerKind pointerKind = JsonPointerKind.Unspecified)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (source == string.Empty)
            {
                pointer = Empty;
                return(true);
            }
            if (source == "#")
            {
                pointer = UrlEmpty;
                return(true);
            }

            bool isUriEncoded;
            var  parts = source.Split('/');
            var  i     = 0;

            if (parts[0] == "#" || parts[0] == string.Empty)
            {
                isUriEncoded = parts[0] == "#";
                i++;
            }
            else
            {
                pointer = default;
                return(false);
            }

            switch (pointerKind)
            {
            case JsonPointerKind.Unspecified:
                break;

            case JsonPointerKind.Plain:
                if (isUriEncoded)
                {
                    pointer = default;
                    return(false);
                }
                break;

            case JsonPointerKind.UriEncoded:
                if (!isUriEncoded)
                {
                    pointer = default;
                    return(false);
                }
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(pointerKind), pointerKind, null);
            }

            var segments = new PointerSegment[parts.Length - i];

            for (; i < parts.Length; i++)
            {
                var part = parts[i];
                if (!PointerSegment.TryParse(part, isUriEncoded, out var segment))
                {
                    pointer = default;
                    return(false);
                }

                segments[i - 1] = segment;
            }

            pointer = new JsonPointer
            {
                _source   = source,
                _segments = segments,
                Kind      = isUriEncoded ? JsonPointerKind.UriEncoded : JsonPointerKind.Plain
            };
            return(true);
        }