mirror of
https://github.com/oarkflow/mq.git
synced 2025-10-05 16:06:55 +08:00
update
This commit is contained in:
@@ -3,364 +3,343 @@ package handlers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/oarkflow/json"
|
||||
"github.com/oarkflow/mq"
|
||||
"github.com/oarkflow/mq/dag"
|
||||
)
|
||||
|
||||
// JSONHandler handles JSON parsing and stringification operations
|
||||
// JSONHandler handles JSON parsing and stringifying operations
|
||||
type JSONHandler struct {
|
||||
dag.Operation
|
||||
OperationType string `json:"operation_type"` // "parse" or "stringify"
|
||||
SourceField string `json:"source_field"` // field containing data to process
|
||||
TargetField string `json:"target_field"` // field to store result
|
||||
Options JSONOptions `json:"options"` // processing options
|
||||
}
|
||||
|
||||
type JSONOptions struct {
|
||||
Pretty bool `json:"pretty"` // pretty print JSON (stringify only)
|
||||
Indent string `json:"indent"` // indentation string (stringify only)
|
||||
EscapeHTML bool `json:"escape_html"` // escape HTML in JSON strings (stringify only)
|
||||
ValidateOnly bool `json:"validate_only"` // only validate, don't parse (parse only)
|
||||
ErrorOnInvalid bool `json:"error_on_invalid"` // return error if JSON is invalid
|
||||
DefaultOnError any `json:"default_on_error"` // default value to use if parsing fails
|
||||
StrictMode bool `json:"strict_mode"` // strict JSON parsing
|
||||
AllowComments bool `json:"allow_comments"` // allow comments in JSON (parse only)
|
||||
AllowTrailing bool `json:"allow_trailing"` // allow trailing commas (parse only)
|
||||
}
|
||||
|
||||
func (j *JSONHandler) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
|
||||
func (h *JSONHandler) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
|
||||
var data map[string]any
|
||||
if err := json.Unmarshal(task.Payload, &data); err != nil {
|
||||
return mq.Result{Error: fmt.Errorf("failed to unmarshal data: %v", err), Ctx: ctx}
|
||||
err := json.Unmarshal(task.Payload, &data)
|
||||
if err != nil {
|
||||
return mq.Result{Error: fmt.Errorf("failed to unmarshal task payload: %w", err)}
|
||||
}
|
||||
|
||||
// Get source value
|
||||
sourceValue, exists := data[j.SourceField]
|
||||
if !exists {
|
||||
return mq.Result{Error: fmt.Errorf("source field '%s' not found", j.SourceField), Ctx: ctx}
|
||||
operation, ok := h.Payload.Data["operation"].(string)
|
||||
if !ok {
|
||||
return mq.Result{Error: fmt.Errorf("operation not specified")}
|
||||
}
|
||||
|
||||
var result any
|
||||
var err error
|
||||
|
||||
switch j.OperationType {
|
||||
case "parse":
|
||||
result, err = j.parseJSON(sourceValue)
|
||||
case "stringify":
|
||||
result, err = j.stringifyJSON(sourceValue)
|
||||
var result map[string]any
|
||||
switch operation {
|
||||
case "parse", "string_to_json":
|
||||
result = h.parseJSON(data)
|
||||
case "stringify", "json_to_string":
|
||||
result = h.stringifyJSON(data)
|
||||
case "pretty_print":
|
||||
result = h.prettyPrintJSON(data)
|
||||
case "minify":
|
||||
result = h.minifyJSON(data)
|
||||
case "validate":
|
||||
result = h.validateJSON(data)
|
||||
case "extract_fields":
|
||||
result = h.extractFields(data)
|
||||
default:
|
||||
return mq.Result{Error: fmt.Errorf("unsupported operation type: %s", j.OperationType), Ctx: ctx}
|
||||
return mq.Result{Error: fmt.Errorf("unsupported operation: %s", operation)}
|
||||
}
|
||||
|
||||
resultPayload, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
if j.Options.ErrorOnInvalid {
|
||||
return mq.Result{Error: err, Ctx: ctx}
|
||||
}
|
||||
// Use default value if specified
|
||||
if j.Options.DefaultOnError != nil {
|
||||
result = j.Options.DefaultOnError
|
||||
} else {
|
||||
result = sourceValue // keep original value
|
||||
}
|
||||
return mq.Result{Error: fmt.Errorf("failed to marshal result: %w", err)}
|
||||
}
|
||||
|
||||
// Set target field
|
||||
targetField := j.TargetField
|
||||
if targetField == "" {
|
||||
targetField = j.SourceField // overwrite source if no target specified
|
||||
}
|
||||
data[targetField] = result
|
||||
|
||||
bt, _ := json.Marshal(data)
|
||||
return mq.Result{Payload: bt, Ctx: ctx}
|
||||
return mq.Result{Payload: resultPayload, Ctx: ctx}
|
||||
}
|
||||
|
||||
func (j *JSONHandler) parseJSON(value any) (any, error) {
|
||||
// Convert value to string
|
||||
jsonStr := fmt.Sprintf("%v", value)
|
||||
func (h *JSONHandler) parseJSON(data map[string]any) map[string]any {
|
||||
result := make(map[string]any)
|
||||
fields := h.getTargetFields()
|
||||
|
||||
// Validate only if requested
|
||||
if j.Options.ValidateOnly {
|
||||
var temp any
|
||||
err := json.Unmarshal([]byte(jsonStr), &temp)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("invalid JSON: %v", err)
|
||||
// Copy all original data
|
||||
for key, value := range data {
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
if val, ok := data[field]; ok {
|
||||
if str, ok := val.(string); ok {
|
||||
var parsed interface{}
|
||||
if err := json.Unmarshal([]byte(str), &parsed); err == nil {
|
||||
targetField := h.getTargetFieldForSource(field)
|
||||
result[targetField] = parsed
|
||||
result[field+"_parsed"] = true
|
||||
} else {
|
||||
result[field+"_parse_error"] = err.Error()
|
||||
result[field+"_parsed"] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Preprocess if needed
|
||||
if j.Options.AllowComments {
|
||||
jsonStr = j.removeComments(jsonStr)
|
||||
}
|
||||
|
||||
if j.Options.AllowTrailing {
|
||||
jsonStr = j.removeTrailingCommas(jsonStr)
|
||||
}
|
||||
|
||||
// Parse JSON
|
||||
var result any
|
||||
err := json.Unmarshal([]byte(jsonStr), &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse JSON: %v", err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (j *JSONHandler) stringifyJSON(value any) (string, error) {
|
||||
var result []byte
|
||||
var err error
|
||||
|
||||
if j.Options.Pretty {
|
||||
indent := j.Options.Indent
|
||||
if indent == "" {
|
||||
indent = " " // default indentation
|
||||
}
|
||||
result, err = json.MarshalIndent(value, "", indent)
|
||||
} else {
|
||||
result, err = json.Marshal(value)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to stringify JSON: %v", err)
|
||||
}
|
||||
|
||||
return string(result), nil
|
||||
}
|
||||
|
||||
func (j *JSONHandler) removeComments(jsonStr string) string {
|
||||
lines := strings.Split(jsonStr, "\n")
|
||||
var cleanLines []string
|
||||
|
||||
for _, line := range lines {
|
||||
// Remove single-line comments
|
||||
if commentIndex := strings.Index(line, "//"); commentIndex != -1 {
|
||||
line = line[:commentIndex]
|
||||
}
|
||||
cleanLines = append(cleanLines, line)
|
||||
}
|
||||
|
||||
result := strings.Join(cleanLines, "\n")
|
||||
|
||||
// Remove multi-line comments (basic implementation)
|
||||
for {
|
||||
start := strings.Index(result, "/*")
|
||||
if start == -1 {
|
||||
break
|
||||
}
|
||||
end := strings.Index(result[start:], "*/")
|
||||
if end == -1 {
|
||||
break
|
||||
}
|
||||
result = result[:start] + result[start+end+2:]
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (j *JSONHandler) removeTrailingCommas(jsonStr string) string {
|
||||
// Basic implementation - remove commas before closing brackets/braces
|
||||
jsonStr = strings.ReplaceAll(jsonStr, ",}", "}")
|
||||
jsonStr = strings.ReplaceAll(jsonStr, ",]", "]")
|
||||
return jsonStr
|
||||
}
|
||||
|
||||
// Advanced JSON handler for complex operations
|
||||
type AdvancedJSONHandler struct {
|
||||
dag.Operation
|
||||
Operations []JSONOperation `json:"operations"` // chain of JSON operations
|
||||
}
|
||||
|
||||
type JSONOperation struct {
|
||||
Type string `json:"type"` // "parse", "stringify", "validate", "extract", "merge"
|
||||
SourceField string `json:"source_field"` // field to operate on
|
||||
TargetField string `json:"target_field"` // field to store result
|
||||
Options JSONOptions `json:"options"` // operation options
|
||||
Path string `json:"path"` // JSON path for extraction (extract only)
|
||||
MergeWith string `json:"merge_with"` // field to merge with (merge only)
|
||||
}
|
||||
|
||||
func (a *AdvancedJSONHandler) ProcessTask(ctx context.Context, task *mq.Task) mq.Result {
|
||||
var data map[string]any
|
||||
if err := json.Unmarshal(task.Payload, &data); err != nil {
|
||||
return mq.Result{Error: fmt.Errorf("failed to unmarshal data: %v", err), Ctx: ctx}
|
||||
}
|
||||
|
||||
// Execute operations in sequence
|
||||
for i, op := range a.Operations {
|
||||
var result any
|
||||
var err error
|
||||
|
||||
switch op.Type {
|
||||
case "parse", "stringify":
|
||||
handler := &JSONHandler{
|
||||
OperationType: op.Type,
|
||||
SourceField: op.SourceField,
|
||||
TargetField: op.TargetField,
|
||||
Options: op.Options,
|
||||
}
|
||||
|
||||
tempData, _ := json.Marshal(data)
|
||||
tempTask := &mq.Task{Payload: tempData}
|
||||
|
||||
handlerResult := handler.ProcessTask(ctx, tempTask)
|
||||
if handlerResult.Error != nil {
|
||||
return mq.Result{Error: fmt.Errorf("operation %d failed: %v", i+1, handlerResult.Error), Ctx: ctx}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(handlerResult.Payload, &data); err != nil {
|
||||
return mq.Result{Error: fmt.Errorf("failed to unmarshal result from operation %d: %v", i+1, err), Ctx: ctx}
|
||||
}
|
||||
continue
|
||||
|
||||
case "validate":
|
||||
result, err = a.validateJSON(data[op.SourceField])
|
||||
case "extract":
|
||||
result, err = a.extractFromJSON(data[op.SourceField], op.Path)
|
||||
case "merge":
|
||||
result, err = a.mergeJSON(data[op.SourceField], data[op.MergeWith])
|
||||
default:
|
||||
return mq.Result{Error: fmt.Errorf("unsupported operation type: %s", op.Type), Ctx: ctx}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if op.Options.ErrorOnInvalid {
|
||||
return mq.Result{Error: fmt.Errorf("operation %d failed: %v", i+1, err), Ctx: ctx}
|
||||
}
|
||||
result = op.Options.DefaultOnError
|
||||
}
|
||||
|
||||
// Set target field
|
||||
targetField := op.TargetField
|
||||
if targetField == "" {
|
||||
targetField = op.SourceField
|
||||
}
|
||||
data[targetField] = result
|
||||
}
|
||||
|
||||
bt, _ := json.Marshal(data)
|
||||
return mq.Result{Payload: bt, Ctx: ctx}
|
||||
}
|
||||
|
||||
func (a *AdvancedJSONHandler) validateJSON(value any) (bool, error) {
|
||||
jsonStr := fmt.Sprintf("%v", value)
|
||||
var temp any
|
||||
err := json.Unmarshal([]byte(jsonStr), &temp)
|
||||
return err == nil, err
|
||||
}
|
||||
|
||||
func (a *AdvancedJSONHandler) extractFromJSON(value any, path string) (any, error) {
|
||||
// Basic JSON path extraction (simplified implementation)
|
||||
// For production use, consider using a proper JSON path library
|
||||
|
||||
var jsonData any
|
||||
if str, ok := value.(string); ok {
|
||||
if err := json.Unmarshal([]byte(str), &jsonData); err != nil {
|
||||
return nil, fmt.Errorf("invalid JSON: %v", err)
|
||||
}
|
||||
} else {
|
||||
jsonData = value
|
||||
}
|
||||
|
||||
// Split path and navigate
|
||||
parts := strings.Split(strings.Trim(path, "."), ".")
|
||||
current := jsonData
|
||||
|
||||
for _, part := range parts {
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
switch v := current.(type) {
|
||||
case map[string]any:
|
||||
current = v[part]
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot navigate path '%s' at part '%s'", path, part)
|
||||
}
|
||||
}
|
||||
|
||||
return current, nil
|
||||
}
|
||||
|
||||
func (a *AdvancedJSONHandler) mergeJSON(value1, value2 any) (any, error) {
|
||||
// Convert both values to maps if they're JSON strings
|
||||
var map1, map2 map[string]any
|
||||
|
||||
if str, ok := value1.(string); ok {
|
||||
if err := json.Unmarshal([]byte(str), &map1); err != nil {
|
||||
return nil, fmt.Errorf("invalid JSON in first value: %v", err)
|
||||
}
|
||||
} else if m, ok := value1.(map[string]any); ok {
|
||||
map1 = m
|
||||
} else {
|
||||
return nil, fmt.Errorf("first value is not a JSON object")
|
||||
}
|
||||
|
||||
if str, ok := value2.(string); ok {
|
||||
if err := json.Unmarshal([]byte(str), &map2); err != nil {
|
||||
return nil, fmt.Errorf("invalid JSON in second value: %v", err)
|
||||
}
|
||||
} else if m, ok := value2.(map[string]any); ok {
|
||||
map2 = m
|
||||
} else {
|
||||
return nil, fmt.Errorf("second value is not a JSON object")
|
||||
}
|
||||
|
||||
// Merge maps
|
||||
func (h *JSONHandler) stringifyJSON(data map[string]any) map[string]any {
|
||||
result := make(map[string]any)
|
||||
for k, v := range map1 {
|
||||
result[k] = v
|
||||
}
|
||||
for k, v := range map2 {
|
||||
result[k] = v // overwrites if key exists
|
||||
fields := h.getTargetFields()
|
||||
indent := h.getIndent()
|
||||
|
||||
// Copy all original data
|
||||
for key, value := range data {
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
return result, nil
|
||||
for _, field := range fields {
|
||||
if val, ok := data[field]; ok {
|
||||
var jsonBytes []byte
|
||||
var err error
|
||||
|
||||
if indent {
|
||||
jsonBytes, err = json.MarshalIndent(val, "", " ")
|
||||
} else {
|
||||
jsonBytes, err = json.Marshal(val)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
targetField := h.getTargetFieldForSource(field)
|
||||
result[targetField] = string(jsonBytes)
|
||||
result[field+"_stringified"] = true
|
||||
} else {
|
||||
result[field+"_stringify_error"] = err.Error()
|
||||
result[field+"_stringified"] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Factory functions
|
||||
func NewJSONParser(id, sourceField, targetField string, options JSONOptions) *JSONHandler {
|
||||
func (h *JSONHandler) prettyPrintJSON(data map[string]any) map[string]any {
|
||||
result := make(map[string]any)
|
||||
fields := h.getTargetFields()
|
||||
|
||||
// Copy all original data
|
||||
for key, value := range data {
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
if val, ok := data[field]; ok {
|
||||
var prettyJSON interface{}
|
||||
|
||||
// If it's a string, try to parse it first
|
||||
if str, ok := val.(string); ok {
|
||||
if err := json.Unmarshal([]byte(str), &prettyJSON); err != nil {
|
||||
prettyJSON = val
|
||||
}
|
||||
} else {
|
||||
prettyJSON = val
|
||||
}
|
||||
|
||||
if jsonBytes, err := json.MarshalIndent(prettyJSON, "", " "); err == nil {
|
||||
targetField := h.getTargetFieldForSource(field)
|
||||
result[targetField] = string(jsonBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (h *JSONHandler) minifyJSON(data map[string]any) map[string]any {
|
||||
result := make(map[string]any)
|
||||
fields := h.getTargetFields()
|
||||
|
||||
// Copy all original data
|
||||
for key, value := range data {
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
if val, ok := data[field]; ok {
|
||||
var minifyJSON interface{}
|
||||
|
||||
// If it's a string, try to parse it first
|
||||
if str, ok := val.(string); ok {
|
||||
if err := json.Unmarshal([]byte(str), &minifyJSON); err != nil {
|
||||
minifyJSON = val
|
||||
}
|
||||
} else {
|
||||
minifyJSON = val
|
||||
}
|
||||
|
||||
if jsonBytes, err := json.Marshal(minifyJSON); err == nil {
|
||||
targetField := h.getTargetFieldForSource(field)
|
||||
result[targetField] = string(jsonBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (h *JSONHandler) validateJSON(data map[string]any) map[string]any {
|
||||
result := make(map[string]any)
|
||||
fields := h.getTargetFields()
|
||||
|
||||
// Copy all original data
|
||||
for key, value := range data {
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
for _, field := range fields {
|
||||
if val, ok := data[field]; ok {
|
||||
if str, ok := val.(string); ok {
|
||||
var temp interface{}
|
||||
if err := json.Unmarshal([]byte(str), &temp); err == nil {
|
||||
result[field+"_valid_json"] = true
|
||||
result[field+"_json_type"] = h.getJSONType(temp)
|
||||
} else {
|
||||
result[field+"_valid_json"] = false
|
||||
result[field+"_validation_error"] = err.Error()
|
||||
}
|
||||
} else {
|
||||
result[field+"_valid_json"] = true
|
||||
result[field+"_json_type"] = h.getJSONType(val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (h *JSONHandler) extractFields(data map[string]any) map[string]any {
|
||||
result := make(map[string]any)
|
||||
sourceField := h.getSourceField()
|
||||
fieldsToExtract := h.getFieldsToExtract()
|
||||
|
||||
// Copy all original data
|
||||
for key, value := range data {
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
if val, ok := data[sourceField]; ok {
|
||||
var jsonData map[string]interface{}
|
||||
|
||||
// If it's a string, parse it
|
||||
if str, ok := val.(string); ok {
|
||||
if err := json.Unmarshal([]byte(str), &jsonData); err != nil {
|
||||
result["extract_error"] = err.Error()
|
||||
return result
|
||||
}
|
||||
} else if obj, ok := val.(map[string]interface{}); ok {
|
||||
jsonData = obj
|
||||
} else {
|
||||
result["extract_error"] = "source field is not a JSON object or string"
|
||||
return result
|
||||
}
|
||||
|
||||
// Extract specified fields
|
||||
for _, fieldPath := range fieldsToExtract {
|
||||
if extractedVal := h.extractNestedField(jsonData, fieldPath); extractedVal != nil {
|
||||
result[fieldPath] = extractedVal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (h *JSONHandler) extractNestedField(data map[string]interface{}, fieldPath string) interface{} {
|
||||
// Simple implementation for dot notation
|
||||
// For more complex path extraction, could use jsonpath library
|
||||
if val, ok := data[fieldPath]; ok {
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *JSONHandler) getJSONType(val interface{}) string {
|
||||
switch val.(type) {
|
||||
case map[string]interface{}:
|
||||
return "object"
|
||||
case []interface{}:
|
||||
return "array"
|
||||
case string:
|
||||
return "string"
|
||||
case float64:
|
||||
return "number"
|
||||
case bool:
|
||||
return "boolean"
|
||||
case nil:
|
||||
return "null"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (h *JSONHandler) getTargetFields() []string {
|
||||
if fields, ok := h.Payload.Data["fields"].([]interface{}); ok {
|
||||
var result []string
|
||||
for _, field := range fields {
|
||||
if str, ok := field.(string); ok {
|
||||
result = append(result, str)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *JSONHandler) getSourceField() string {
|
||||
if field, ok := h.Payload.Data["source_field"].(string); ok {
|
||||
return field
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (h *JSONHandler) getFieldsToExtract() []string {
|
||||
if fields, ok := h.Payload.Data["extract_fields"].([]interface{}); ok {
|
||||
var result []string
|
||||
for _, field := range fields {
|
||||
if str, ok := field.(string); ok {
|
||||
result = append(result, str)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *JSONHandler) getTargetFieldForSource(sourceField string) string {
|
||||
// Check if there's a specific mapping
|
||||
if mapping, ok := h.Payload.Data["field_mapping"].(map[string]interface{}); ok {
|
||||
if target, ok := mapping[sourceField].(string); ok {
|
||||
return target
|
||||
}
|
||||
}
|
||||
|
||||
// Default: append suffix based on operation
|
||||
operation, _ := h.Payload.Data["operation"].(string)
|
||||
switch operation {
|
||||
case "parse", "string_to_json":
|
||||
return sourceField + "_parsed"
|
||||
case "stringify", "json_to_string":
|
||||
return sourceField + "_string"
|
||||
case "pretty_print":
|
||||
return sourceField + "_pretty"
|
||||
case "minify":
|
||||
return sourceField + "_minified"
|
||||
default:
|
||||
return sourceField + "_result"
|
||||
}
|
||||
}
|
||||
|
||||
func (h *JSONHandler) getIndent() bool {
|
||||
if indent, ok := h.Payload.Data["indent"].(bool); ok {
|
||||
return indent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func NewJSONHandler(id string) *JSONHandler {
|
||||
return &JSONHandler{
|
||||
Operation: dag.Operation{
|
||||
ID: id,
|
||||
Key: "json_parse",
|
||||
Type: dag.Function,
|
||||
Tags: []string{"data", "json", "parse"},
|
||||
},
|
||||
OperationType: "parse",
|
||||
SourceField: sourceField,
|
||||
TargetField: targetField,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
func NewJSONStringifier(id, sourceField, targetField string, options JSONOptions) *JSONHandler {
|
||||
return &JSONHandler{
|
||||
Operation: dag.Operation{
|
||||
ID: id,
|
||||
Key: "json_stringify",
|
||||
Type: dag.Function,
|
||||
Tags: []string{"data", "json", "stringify"},
|
||||
},
|
||||
OperationType: "stringify",
|
||||
SourceField: sourceField,
|
||||
TargetField: targetField,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
func NewAdvancedJSONHandler(id string, operations []JSONOperation) *AdvancedJSONHandler {
|
||||
return &AdvancedJSONHandler{
|
||||
Operation: dag.Operation{
|
||||
ID: id,
|
||||
Key: "advanced_json",
|
||||
Type: dag.Function,
|
||||
Tags: []string{"data", "json", "advanced"},
|
||||
},
|
||||
Operations: operations,
|
||||
Operation: dag.Operation{ID: id, Key: "json", Type: dag.Function, Tags: []string{"data", "transformation", "json"}},
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user