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<MyBean> <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}