-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-17764][SQL] Add to_json supporting to convert nested struct column to JSON string
#15354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3dbfc69
84a93b6
48e097e
abed158
b1632ba
b4cf8a1
971d1c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,16 +17,17 @@ | |
|
|
||
| package org.apache.spark.sql.catalyst.expressions | ||
|
|
||
| import java.io.{ByteArrayOutputStream, StringWriter} | ||
| import java.io.{ByteArrayOutputStream, CharArrayWriter, StringWriter} | ||
|
|
||
| import scala.util.parsing.combinator.RegexParsers | ||
|
|
||
| import com.fasterxml.jackson.core._ | ||
|
|
||
| import org.apache.spark.sql.AnalysisException | ||
| import org.apache.spark.sql.catalyst.analysis.TypeCheckResult | ||
| import org.apache.spark.sql.catalyst.expressions.codegen.CodegenFallback | ||
| import org.apache.spark.sql.catalyst.InternalRow | ||
| import org.apache.spark.sql.catalyst.json.{JacksonParser, JSONOptions, SparkSQLJsonProcessingException} | ||
| import org.apache.spark.sql.catalyst.json._ | ||
| import org.apache.spark.sql.catalyst.util.ParseModes | ||
| import org.apache.spark.sql.types._ | ||
| import org.apache.spark.unsafe.types.UTF8String | ||
|
|
@@ -494,3 +495,46 @@ case class JsonToStruct(schema: StructType, options: Map[String, String], child: | |
|
|
||
| override def inputTypes: Seq[AbstractDataType] = StringType :: Nil | ||
| } | ||
|
|
||
| /** | ||
| * Converts a [[StructType]] to a json output string. | ||
| */ | ||
| case class StructToJson(options: Map[String, String], child: Expression) | ||
| extends Expression with CodegenFallback with ExpectsInputTypes { | ||
| override def nullable: Boolean = true | ||
|
|
||
| @transient | ||
| lazy val writer = new CharArrayWriter() | ||
|
|
||
| @transient | ||
| lazy val gen = | ||
| new JacksonGenerator(child.dataType.asInstanceOf[StructType], writer) | ||
|
|
||
| override def dataType: DataType = StringType | ||
| override def children: Seq[Expression] = child :: Nil | ||
|
|
||
| override def checkInputDataTypes(): TypeCheckResult = { | ||
| if (StructType.acceptsType(child.dataType)) { | ||
| try { | ||
|
||
| JacksonUtils.verifySchema(child.dataType.asInstanceOf[StructType]) | ||
| TypeCheckResult.TypeCheckSuccess | ||
| } catch { | ||
| case e: UnsupportedOperationException => | ||
| TypeCheckResult.TypeCheckFailure(e.getMessage) | ||
| } | ||
| } else { | ||
| TypeCheckResult.TypeCheckFailure( | ||
| s"$prettyName requires that the expression is a struct expression.") | ||
| } | ||
| } | ||
|
|
||
| override def eval(input: InternalRow): Any = { | ||
| gen.write(child.eval(input).asInstanceOf[InternalRow]) | ||
| gen.flush() | ||
| val json = writer.toString | ||
| writer.reset() | ||
| UTF8String.fromString(json) | ||
| } | ||
|
|
||
| override def inputTypes: Seq[AbstractDataType] = StructType :: Nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is super minor, but there is a pretty consistent pattern for all of the other functions here (including
from_json), it might be good to follow that same pattern for consistencies sake since there isn't an obvious reason why that wouldn't work here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@holdenk Thank you for your comment. Could you please a bit elaborate this comment? I am a bit not sure on what to fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually nvm my original comment, the more I look at this file the less it seems the pattern is overly consistent and this same pattern is done elsewhere within the file.