@@ -48,6 +48,10 @@ class TestFileFilter extends PathFilter {
4848class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
4949 import testImplicits ._
5050
51+ def testFile (fileName : String ): String = {
52+ Thread .currentThread().getContextClassLoader.getResource(fileName).toString
53+ }
54+
5155 test(" Type promotion" ) {
5256 def checkTypePromotion (expected : Any , actual : Any ) {
5357 assert(expected.getClass == actual.getClass,
@@ -2168,12 +2172,8 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
21682172 assert(sampled.count() == ds.count())
21692173 }
21702174
2171- def testFile (fileName : String ): String = {
2172- Thread .currentThread().getContextClassLoader.getResource(fileName).toString
2173- }
2174-
21752175 test(" SPARK-23723: json in UTF-16 with BOM" ) {
2176- val fileName = " json-tests /utf16WithBOM.json"
2176+ val fileName = " test-data /utf16WithBOM.json"
21772177 val schema = new StructType ().add(" firstName" , StringType ).add(" lastName" , StringType )
21782178 val jsonDF = spark.read.schema(schema)
21792179 .option(" multiline" , " true" )
@@ -2184,7 +2184,7 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
21842184 }
21852185
21862186 test(" SPARK-23723: multi-line json in UTF-32BE with BOM" ) {
2187- val fileName = " json-tests /utf32BEWithBOM.json"
2187+ val fileName = " test-data /utf32BEWithBOM.json"
21882188 val schema = new StructType ().add(" firstName" , StringType ).add(" lastName" , StringType )
21892189 val jsonDF = spark.read.schema(schema)
21902190 .option(" multiline" , " true" )
@@ -2194,7 +2194,7 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
21942194 }
21952195
21962196 test(" SPARK-23723: Use user's encoding in reading of multi-line json in UTF-16LE" ) {
2197- val fileName = " json-tests /utf16LE.json"
2197+ val fileName = " test-data /utf16LE.json"
21982198 val schema = new StructType ().add(" firstName" , StringType ).add(" lastName" , StringType )
21992199 val jsonDF = spark.read.schema(schema)
22002200 .option(" multiline" , " true" )
@@ -2209,15 +2209,15 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
22092209 val exception = intercept[UnsupportedCharsetException ] {
22102210 spark.read
22112211 .options(Map (" encoding" -> invalidCharset, " lineSep" -> " \n " ))
2212- .json(testFile(" json-tests /utf16LE.json" ))
2212+ .json(testFile(" test-data /utf16LE.json" ))
22132213 .count()
22142214 }
22152215
22162216 assert(exception.getMessage.contains(invalidCharset))
22172217 }
22182218
22192219 test(" SPARK-23723: checking that the encoding option is case agnostic" ) {
2220- val fileName = " json-tests /utf16LE.json"
2220+ val fileName = " test-data /utf16LE.json"
22212221 val schema = new StructType ().add(" firstName" , StringType ).add(" lastName" , StringType )
22222222 val jsonDF = spark.read.schema(schema)
22232223 .option(" multiline" , " true" )
@@ -2229,7 +2229,7 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
22292229
22302230
22312231 test(" SPARK-23723: specified encoding is not matched to actual encoding" ) {
2232- val fileName = " json-tests /utf16LE.json"
2232+ val fileName = " test-data /utf16LE.json"
22332233 val schema = new StructType ().add(" firstName" , StringType ).add(" lastName" , StringType )
22342234 val exception = intercept[SparkException ] {
22352235 spark.read.schema(schema)
@@ -2244,17 +2244,15 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
22442244 assert(errMsg.contains(" Malformed records are detected in record parsing" ))
22452245 }
22462246
2247- def checkEncoding (
2248- expectedEncoding : String ,
2249- pathToJsonFiles : String ,
2247+ def checkEncoding (expectedEncoding : String , pathToJsonFiles : String ,
22502248 expectedContent : String ): Unit = {
22512249 val jsonFiles = new File (pathToJsonFiles)
22522250 .listFiles()
22532251 .filter(_.isFile)
22542252 .filter(_.getName.endsWith(" json" ))
22552253 val actualContent = jsonFiles.map { file =>
22562254 new String (Files .readAllBytes(file.toPath), expectedEncoding)
2257- }.mkString.trim.replaceAll( " " , " " )
2255+ }.mkString.trim
22582256
22592257 assert(actualContent == expectedContent)
22602258 }
@@ -2265,8 +2263,7 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
22652263 val df = spark.createDataset(Seq ((" Dog" , 42 )))
22662264 df.write
22672265 .options(Map (" encoding" -> encoding, " lineSep" -> " \n " ))
2268- .format(" json" ).mode(" overwrite" )
2269- .save(path.getCanonicalPath)
2266+ .json(path.getCanonicalPath)
22702267
22712268 checkEncoding(
22722269 expectedEncoding = encoding,
@@ -2278,9 +2275,7 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
22782275 test(" SPARK-23723: save json in default encoding - UTF-8" ) {
22792276 withTempPath { path =>
22802277 val df = spark.createDataset(Seq ((" Dog" , 42 )))
2281- df.write
2282- .format(" json" ).mode(" overwrite" )
2283- .save(path.getCanonicalPath)
2278+ df.write.json(path.getCanonicalPath)
22842279
22852280 checkEncoding(
22862281 expectedEncoding = " UTF-8" ,
@@ -2296,24 +2291,19 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
22962291 val df = spark.createDataset(Seq ((0 )))
22972292 df.write
22982293 .options(Map (" encoding" -> encoding, " lineSep" -> " \n " ))
2299- .format(" json" ).mode(" overwrite" )
2300- .save(path.getCanonicalPath)
2294+ .json(path.getCanonicalPath)
23012295 }
23022296 }
23032297
23042298 assert(exception.getMessage == encoding)
23052299 }
23062300
2307- test(" SPARK-23723: read written json in UTF-16LE" ) {
2301+ test(" SPARK-23723: read back json in UTF-16LE" ) {
23082302 val options = Map (" encoding" -> " UTF-16LE" , " lineSep" -> " \n " )
23092303 withTempPath { path =>
2310- val ds = spark.createDataset(Seq (
2311- (" a" , 1 ), (" b" , 2 ), (" c" , 3 ))
2312- ).repartition(2 )
2313- ds.write
2314- .options(options)
2315- .format(" json" ).mode(" overwrite" )
2316- .save(path.getCanonicalPath)
2304+ val ds = spark.createDataset(Seq ((" a" , 1 ), (" b" , 2 ), (" c" , 3 ))).repartition(2 )
2305+ ds.write.options(options).json(path.getCanonicalPath)
2306+
23172307 val readBack = spark
23182308 .read
23192309 .options(options)
@@ -2325,20 +2315,12 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
23252315
23262316 def checkReadJson (lineSep : String , encoding : String , inferSchema : Boolean , id : Int ): Unit = {
23272317 test(s " SPARK-23724: checks reading json in ${encoding} # ${id}" ) {
2328- val lineSepInBytes = {
2329- if (lineSep.startsWith(" x" )) {
2330- lineSep.replaceAll(" [^0-9A-Fa-f]" , " " )
2331- .sliding(2 , 2 ).toArray.map(Integer .parseInt(_, 16 ).toByte)
2332- } else {
2333- lineSep.getBytes(encoding)
2334- }
2335- }
23362318 val schema = new StructType ().add(" f1" , StringType ).add(" f2" , IntegerType )
23372319 withTempPath { path =>
23382320 val records = List ((" a" , 1 ), (" b" , 2 ))
23392321 val data = records
23402322 .map(rec => s """ {"f1":" ${rec._1}", "f2": ${rec._2}} """ .getBytes(encoding))
2341- .reduce((a1, a2) => a1 ++ lineSepInBytes ++ a2)
2323+ .reduce((a1, a2) => a1 ++ lineSep.getBytes(encoding) ++ a2)
23422324 val os = new FileOutputStream (path)
23432325 os.write(data)
23442326 os.close()
@@ -2372,15 +2354,17 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
23722354 (11 , " \u000a\u000d " , " UTF-8" , true ),
23732355 (12 , " ===" , " US-ASCII" , false ),
23742356 (13 , " $^+" , " utf-32le" , true )
2375- ).foreach{case (i, d, c, s) => checkReadJson(d, c, s, i)}
2357+ ).foreach {
2358+ case (testNum, sep, encoding, inferSchema) => checkReadJson(sep, encoding, inferSchema, testNum)
2359+ }
23762360 // scalastyle:on nonascii
23772361
23782362 test(" SPARK-23724: lineSep should be set if encoding if different from UTF-8" ) {
23792363 val encoding = " UTF-16LE"
23802364 val exception = intercept[IllegalArgumentException ] {
23812365 spark.read
23822366 .options(Map (" encoding" -> encoding))
2383- .json(testFile(" json-tests /utf16LE.json" ))
2367+ .json(testFile(" test-data /utf16LE.json" ))
23842368 .count()
23852369 }
23862370
@@ -2390,36 +2374,38 @@ class JsonSuite extends QueryTest with SharedSQLContext with TestJsonData {
23902374
23912375 private val badJson = " \u0000\u0000\u0000 A\u0001 AAA"
23922376
2393- test(" SPARK-23094: invalid json with leading nulls - from file (multiLine=true) " ) {
2394- withTempDir { tempDir =>
2377+ test(" SPARK-23094: permissively read JSON file with leading nulls when multiLine is enabled " ) {
2378+ withTempPath { tempDir =>
23952379 val path = tempDir.getAbsolutePath
2396- Seq (badJson + """ {"a":1}""" ).toDS().write.mode( " overwrite " ). text(path)
2380+ Seq (badJson + """ {"a":1}""" ).toDS().write.text(path)
23972381 val expected = s """ ${badJson}{"a":1}\n """
23982382 val schema = new StructType ().add(" a" , IntegerType ).add(" _corrupt_record" , StringType )
23992383 val df = spark.read.format(" json" )
2384+ .option(" mode" , " PERMISSIVE" )
24002385 .option(" multiLine" , true )
24012386 .option(" encoding" , " UTF-8" )
24022387 .schema(schema).load(path)
24032388 checkAnswer(df, Row (null , expected))
24042389 }
24052390 }
24062391
2407- test(" SPARK-23094: invalid json with leading nulls - from file (multiLine=false) " ) {
2408- withTempDir { tempDir =>
2392+ test(" SPARK-23094: permissively read JSON file with leading nulls when multiLine is disabled " ) {
2393+ withTempPath { tempDir =>
24092394 val path = tempDir.getAbsolutePath
2410- Seq (badJson, """ {"a":1}""" ).toDS().write.mode( " overwrite " ). text(path)
2395+ Seq (badJson, """ {"a":1}""" ).toDS().write.text(path)
24112396 val schema = new StructType ().add(" a" , IntegerType ).add(" _corrupt_record" , StringType )
24122397 val df = spark.read.format(" json" )
2398+ .option(" mode" , " PERMISSIVE" )
24132399 .option(" multiLine" , false )
24142400 .option(" encoding" , " UTF-8" )
24152401 .schema(schema).load(path)
24162402 checkAnswer(df, Seq (Row (1 , null ), Row (null , badJson)))
24172403 }
24182404 }
24192405
2420- test(" SPARK-23094: invalid json with leading nulls - from dataset " ) {
2406+ test(" SPARK-23094: permissively parse a dataset contains JSON with leading nulls " ) {
24212407 checkAnswer(
2422- spark.read.option(" encoding" , " UTF-8" ).json(Seq (badJson).toDS()),
2408+ spark.read.option(" mode " , " PERMISSIVE " ).option( " encoding" , " UTF-8" ).json(Seq (badJson).toDS()),
24232409 Row (badJson))
24242410 }
24252411}
0 commit comments