001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.marshall.jsonl;
018
019import java.util.*;
020
021import org.apache.juneau.marshall.collections.*;
022import org.apache.juneau.marshall.json.*;
023
024/**
025 * Parses JSONL (JSON Lines) input into POJO models.
026 *
027 * <h5 class='topic'>Media types</h5>
028 * <p>
029 * Handles <c>Content-Type</c> types:  <bc>application/jsonl, application/jsonlines, application/x-ndjson, text/jsonl</bc>
030 *
031 * <h5 class='topic'>Description</h5>
032 * <p>
033 * Parses JSONL input where each non-empty line is a complete JSON value.  Blank lines are ignored.
034 * The conversion is as follows...
035 * <ul class='spaced-list'>
036 *    <li>JSON objects (<c>{...}</c>) are converted to {@link JsonMap JsonMaps}
037 *       or Java beans if a target type is provided.
038 *    <li>JSON arrays (<c>[...]</c>) are converted to {@link JsonList JsonLists}.
039 *    <li>JSON strings are converted to {@link String Strings}.
040 *    <li>JSON numbers are converted to {@link Integer Integers}, {@link Long Longs},
041 *       {@link Float Floats}, or {@link Double Doubles}.
042 *    <li>JSON booleans are converted to {@link Boolean Booleans}.
043 *    <li>JSON nulls are converted to <jk>null</jk>.
044 * </ul>
045 * <p>
046 * When the target type is a {@link Collection} or array, each line is parsed
047 * as one element.  When the target type is a single value, only the first non-empty line is parsed.
048 *
049 * <h5 class='section'>Example:</h5>
050 * <p class='bjava'>
051 *    <jc>// Use the default parser to parse JSONL into a list of POJOs</jc>
052 *    List&lt;MyBean&gt; <jv>list</jv> = JsonlParser.<jsf>DEFAULT</jsf>.read(<jv>jsonlInput</jv>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
053 *
054 *    <jc>// Create a custom parser</jc>
055 *    JsonlParser <jv>parser</jv> = JsonlParser.<jsm>create</jsm>().build();
056 *
057 *    <jc>// Clone an existing parser</jc>
058 *    <jv>parser</jv> = JsonlParser.<jsf>DEFAULT</jsf>.copy().build();
059 * </p>
060 *
061 * <h5 class='figure'>Example input:</h5>
062 * <p class='bjson'>
063 * {"name":"Alice","age":30}
064 * {"name":"Bob","age":25}
065 * {"name":"Carol","age":35}
066 * </p>
067 *
068 * <h5 class='section'>Limitations compared to JSON</h5>
069 * <p>
070 * <ul class='spaced-list'>
071 *    <li><b>No multi-line JSON input</b>: Each JSON value must be on a single line.
072 *       Multi-line (pretty-printed) JSON piped as JSONL input will cause parse errors.
073 *    <li><b>First-line-only for non-collection targets</b>: When parsing JSONL to a single
074 *       non-collection type, only the first non-empty line is parsed; trailing lines are
075 *       silently ignored.
076 * </ul>
077 *
078 * <h5 class='section'>Notes:</h5><ul>
079 *    <li class='note'>This class is thread safe and reusable.
080 * </ul>
081 *
082 * <h5 class='section'>See Also:</h5><ul>
083 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JsonlSupport">JSONL</a>
084 * </ul>
085 */
086@SuppressWarnings({
087   "java:S110", // Inheritance depth acceptable
088   "java:S9149" // Per-format static factories intentionally shadow the parent's.
089})
090public class JsonlParser extends JsonParser {
091
092   /** Default parser. */
093   public static final JsonlParser DEFAULT = new JsonlParser(create());
094
095   /**
096    * Creates a new builder for this object.
097    *
098    * @return A new builder.
099    */
100   @SuppressWarnings({
101      "java:S1452" // Builder<?> wildcard return intentional; callers chain via fluent API without needing the concrete type
102   })
103   public static JsonParser.Builder<?> create() {
104      return JsonParser.create()
105         .consumes("application/jsonl,application/jsonlines,application/x-ndjson,text/jsonl")
106         .type(JsonlParser.class);
107   }
108
109   /**
110    * Constructor.
111    *
112    * @param builder The builder for this object.
113    */
114   public JsonlParser(JsonParser.Builder<?> builder) {
115      super(builder);
116   }
117
118   @Override /* Overridden from Context */
119   public JsonlParserSession.Builder createSession() {
120      return JsonlParserSession.create(this);
121   }
122
123}