aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOskari Timperi <oskari.timperi@iki.fi>2018-04-08 16:13:00 +0300
committerOskari Timperi <oskari.timperi@iki.fi>2018-04-08 16:13:00 +0300
commitd94b73731fb7da1f42f2bf0a6293070690bb9a5c (patch)
tree492c6d0f0a7ae5d77e2c3001296ccb695549c99d
parentc065aed3140018bd2717566b21ec462c45ffe2a1 (diff)
downloadnimpb-d94b73731fb7da1f42f2bf0a6293070690bb9a5c.tar.gz
nimpb-d94b73731fb7da1f42f2bf0a6293070690bb9a5c.zip
Add initial message to JSON serialization support
-rw-r--r--src/nimpb/json.nim209
-rw-r--r--src/nimpb/wkt/any_pb.nim3
-rw-r--r--src/nimpb/wkt/api_pb.nim59
-rw-r--r--src/nimpb/wkt/duration_pb.nim3
-rw-r--r--src/nimpb/wkt/empty_pb.nim7
-rw-r--r--src/nimpb/wkt/field_mask_pb.nim3
-rw-r--r--src/nimpb/wkt/source_context_pb.nim9
-rw-r--r--src/nimpb/wkt/struct_pb.nim3
-rw-r--r--src/nimpb/wkt/timestamp_pb.nim3
-rw-r--r--src/nimpb/wkt/type_pb.nim96
-rw-r--r--src/nimpb/wkt/wrappers_pb.nim3
-rw-r--r--tests/conformance/conformance_nim.nim20
-rw-r--r--tests/conformance/failures.txt18
13 files changed, 431 insertions, 5 deletions
diff --git a/src/nimpb/json.nim b/src/nimpb/json.nim
new file mode 100644
index 0000000..28cd0f5
--- /dev/null
+++ b/src/nimpb/json.nim
@@ -0,0 +1,209 @@
+import base64
+import math
+import std/json
+import strutils
+import times
+
+import nimpb
+
+import wkt/duration_pb
+import wkt/timestamp_pb
+import wkt/wrappers_pb
+import wkt/field_mask_pb
+import wkt/struct_pb
+import wkt/any_pb
+
+proc `%`*(u: uint32): JsonNode =
+ newJFloat(float(u))
+
+proc `%`*(b: bytes): JsonNode =
+ result = newJString(base64.encode(string(b), newLine=""))
+
+proc toJson*(value: float): JsonNode =
+ case classify(value)
+ of fcNan: result = %"NaN"
+ of fcInf: result = %"Infinity"
+ of fcNegInf: result = %"-Infinity"
+ else: result = %value
+
+proc toJson*(value: float32): JsonNode =
+ case classify(value)
+ of fcNan: result = %"NaN"
+ of fcInf: result = %"Infinity"
+ of fcNegInf: result = %"-Infinity"
+ else: result = %value
+
+proc toJson*(value: int64): JsonNode =
+ newJString($value)
+
+proc toJson*(value: uint64): JsonNode =
+ newJString($value)
+
+proc toJson*(message: google_protobuf_DoubleValue): JsonNode =
+ if hasValue(message):
+ result = toJson(message.value)
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_FloatValue): JsonNode =
+ if hasValue(message):
+ result = toJson(message.value)
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_Int64Value): JsonNode =
+ if hasValue(message):
+ result = toJson(message.value)
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_UInt64Value): JsonNode =
+ if hasValue(message):
+ result = toJson(message.value)
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_Int32Value): JsonNode =
+ if hasValue(message):
+ result = %message.value
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_UInt32Value): JsonNode =
+ if hasValue(message):
+ result = %message.value
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_BoolValue): JsonNode =
+ if hasValue(message):
+ result = %message.value
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_StringValue): JsonNode =
+ if hasValue(message):
+ result = %message.value
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_BytesValue): JsonNode =
+ if hasValue(message):
+ result = %message.value
+ else:
+ result = newJNull()
+
+proc toJson*(message: google_protobuf_Duration): JsonNode =
+ if (message.seconds < -315_576_000_000'i64) or
+ (message.seconds > 315_576_000_000'i64):
+ raise newException(ValueError, "seconds out of bounds")
+
+ if (message.nanos < -999_999_999'i32) or
+ (message.nanos > 999_999_999'i32):
+ raise newException(ValueError, "nanos out of bounds")
+
+ if message.seconds != 0:
+ if sgn(message.seconds) != sgn(message.nanos):
+ raise newException(ValueError, "different sign for seconds and nanos")
+
+ var s = $message.seconds
+
+ if message.nanos != 0:
+ add(s, ".")
+ add(s, intToStr(message.nanos, 9))
+ removeSuffix(s, '0')
+
+ add(s, "s")
+
+ result = %s
+
+proc toJson*(message: google_protobuf_Timestamp): JsonNode =
+ let t = utc(fromUnix(message.seconds))
+
+ if t.year < 1 or t.year > 9999:
+ raise newException(ValueError, "invalid timestamp")
+
+ var s = format(t, "yyyy-MM-dd'T'HH:mm:ss")
+ if message.nanos != 0:
+ add(s, ".")
+ add(s, intToStr(message.nanos, 9))
+ removeSuffix(s, '0')
+ add(s, "Z")
+ result = %s
+
+proc toJson*(message: google_protobuf_FieldMask): JsonNode =
+ %join(message.paths, ",")
+
+proc toJson*(message: google_protobuf_Value): JsonNode
+
+proc toJson*(message: google_protobuf_Struct): JsonNode =
+ result = newJObject()
+ for key, value in message.fields:
+ result[key] = toJson(value)
+
+proc toJson*(message: google_protobuf_ListValue): JsonNode
+
+proc toJson*(message: google_protobuf_Value): JsonNode =
+ if hasNullValue(message):
+ result = newJNull()
+ elif hasNumberValue(message):
+ result = toJson(message.numberValue)
+ elif hasStringValue(message):
+ result = %message.stringValue
+ elif hasBoolValue(message):
+ result = %message.boolValue
+ elif hasStructValue(message):
+ result = toJson(message.structValue)
+ elif hasListValue(message):
+ result = toJson(message.listValue)
+ else:
+ raise newException(ValueError, "no field set")
+
+proc toJson*(message: google_protobuf_NullValue): JsonNode =
+ newJNull()
+
+proc toJson*(message: google_protobuf_ListValue): JsonNode =
+ result = newJArray()
+ for value in message.values:
+ add(result, toJson(value))
+
+proc toJson*(message: google_protobuf_Any): JsonNode =
+ case message.typeUrl
+ of "type.googleapis.com/google.protobuf.Duration":
+ let duration = newGoogleProtobufDuration(string(message.value))
+ result = newJObject()
+ result["@type"] = %message.typeUrl
+ result["value"] = toJson(duration)
+ of "type.googleapis.com/google.protobuf.Empty":
+ result = newJObject()
+ result["@type"] = %message.typeUrl
+ result["value"] = newJObject()
+ of "type.googleapis.com/google.protobuf.FieldMask":
+ let mask = newGoogleProtobufFieldMask(string(message.value))
+ result = newJObject()
+ result["@type"] = %message.typeUrl
+ result["value"] = toJson(mask)
+ of "type.googleapis.com/google.protobuf.Struct":
+ let struct = newGoogleProtobufStruct(string(message.value))
+ result = newJObject()
+ result["@type"] = %message.typeUrl
+ result["value"] = toJson(struct)
+ of "type.googleapis.com/google.protobuf.Value":
+ let value = newGoogleProtobufValue(string(message.value))
+ result = newJObject()
+ result["@type"] = %message.typeUrl
+ result["value"] = toJson(value)
+ of "type.googleapis.com/google.protobuf.ListValue":
+ let lst = newGoogleProtobufListValue(string(message.value))
+ result = newJObject()
+ result["@type"] = %message.typeUrl
+ result["value"] = toJson(lst)
+ of "type.googleapis.com/google.protobuf.Timestamp":
+ let value = newGoogleProtobufTimestamp(string(message.value))
+ result = newJObject()
+ result["@type"] = %message.typeUrl
+ result["value"] = toJson(value)
+ else:
+ result = newJObject()
+ result["typeUrl"] = %message.typeUrl
+ result["value"] = %message.value
diff --git a/src/nimpb/wkt/any_pb.nim b/src/nimpb/wkt/any_pb.nim
index a452870..aa6f56c 100644
--- a/src/nimpb/wkt/any_pb.nim
+++ b/src/nimpb/wkt/any_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
type
google_protobuf_Any* = ref google_protobuf_AnyObj
diff --git a/src/nimpb/wkt/api_pb.nim b/src/nimpb/wkt/api_pb.nim
index 21b4a6d..28f5b2b 100644
--- a/src/nimpb/wkt/api_pb.nim
+++ b/src/nimpb/wkt/api_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
import nimpb/wkt/source_context_pb
import nimpb/wkt/type_pb
@@ -42,18 +45,21 @@ proc newgoogle_protobuf_Method*(data: string): google_protobuf_Method
proc writegoogle_protobuf_Method*(stream: ProtobufStream, message: google_protobuf_Method)
proc readgoogle_protobuf_Method*(stream: ProtobufStream): google_protobuf_Method
proc sizeOfgoogle_protobuf_Method*(message: google_protobuf_Method): uint64
+proc toJson*(message: google_protobuf_Method): JsonNode
proc newgoogle_protobuf_Mixin*(): google_protobuf_Mixin
proc newgoogle_protobuf_Mixin*(data: string): google_protobuf_Mixin
proc writegoogle_protobuf_Mixin*(stream: ProtobufStream, message: google_protobuf_Mixin)
proc readgoogle_protobuf_Mixin*(stream: ProtobufStream): google_protobuf_Mixin
proc sizeOfgoogle_protobuf_Mixin*(message: google_protobuf_Mixin): uint64
+proc toJson*(message: google_protobuf_Mixin): JsonNode
proc newgoogle_protobuf_Api*(): google_protobuf_Api
proc newgoogle_protobuf_Api*(data: string): google_protobuf_Api
proc writegoogle_protobuf_Api*(stream: ProtobufStream, message: google_protobuf_Api)
proc readgoogle_protobuf_Api*(stream: ProtobufStream): google_protobuf_Api
proc sizeOfgoogle_protobuf_Api*(message: google_protobuf_Api): uint64
+proc toJson*(message: google_protobuf_Api): JsonNode
proc newgoogle_protobuf_Method*(): google_protobuf_Method =
new(result)
@@ -265,6 +271,26 @@ proc readgoogle_protobuf_Method*(stream: ProtobufStream): google_protobuf_Method
setsyntax(result, readEnum[google_protobuf_Syntax](stream))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_Method): JsonNode =
+ result = newJObject()
+ if hasname(message):
+ result["name"] = %message.name
+ if hasrequest_type_url(message):
+ result["requestTypeUrl"] = %message.request_type_url
+ if hasrequest_streaming(message):
+ result["requestStreaming"] = %message.request_streaming
+ if hasresponse_type_url(message):
+ result["responseTypeUrl"] = %message.response_type_url
+ if hasresponse_streaming(message):
+ result["responseStreaming"] = %message.response_streaming
+ if hasoptions(message):
+ let arr = newJArray()
+ for value in message.options:
+ add(arr, toJson(value))
+ result["options"] = arr
+ if hassyntax(message):
+ result["syntax"] = %($message.syntax)
+
proc serialize*(message: google_protobuf_Method): string =
let
ss = newStringStream()
@@ -354,6 +380,13 @@ proc readgoogle_protobuf_Mixin*(stream: ProtobufStream): google_protobuf_Mixin =
setroot(result, readString(stream))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_Mixin): JsonNode =
+ result = newJObject()
+ if hasname(message):
+ result["name"] = %message.name
+ if hasroot(message):
+ result["root"] = %message.root
+
proc serialize*(message: google_protobuf_Mixin): string =
let
ss = newStringStream()
@@ -589,6 +622,32 @@ proc readgoogle_protobuf_Api*(stream: ProtobufStream): google_protobuf_Api =
setsyntax(result, readEnum[google_protobuf_Syntax](stream))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_Api): JsonNode =
+ result = newJObject()
+ if hasname(message):
+ result["name"] = %message.name
+ if hasmethods(message):
+ let arr = newJArray()
+ for value in message.methods:
+ add(arr, toJson(value))
+ result["methods"] = arr
+ if hasoptions(message):
+ let arr = newJArray()
+ for value in message.options:
+ add(arr, toJson(value))
+ result["options"] = arr
+ if hasversion(message):
+ result["version"] = %message.version
+ if hassource_context(message):
+ result["sourceContext"] = toJson(message.source_context)
+ if hasmixins(message):
+ let arr = newJArray()
+ for value in message.mixins:
+ add(arr, toJson(value))
+ result["mixins"] = arr
+ if hassyntax(message):
+ result["syntax"] = %($message.syntax)
+
proc serialize*(message: google_protobuf_Api): string =
let
ss = newStringStream()
diff --git a/src/nimpb/wkt/duration_pb.nim b/src/nimpb/wkt/duration_pb.nim
index f2b5360..d15aeee 100644
--- a/src/nimpb/wkt/duration_pb.nim
+++ b/src/nimpb/wkt/duration_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
type
google_protobuf_Duration* = ref google_protobuf_DurationObj
diff --git a/src/nimpb/wkt/empty_pb.nim b/src/nimpb/wkt/empty_pb.nim
index e36260f..c53cb03 100644
--- a/src/nimpb/wkt/empty_pb.nim
+++ b/src/nimpb/wkt/empty_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
type
google_protobuf_Empty* = ref google_protobuf_EmptyObj
@@ -15,6 +18,7 @@ proc newgoogle_protobuf_Empty*(data: string): google_protobuf_Empty
proc writegoogle_protobuf_Empty*(stream: ProtobufStream, message: google_protobuf_Empty)
proc readgoogle_protobuf_Empty*(stream: ProtobufStream): google_protobuf_Empty
proc sizeOfgoogle_protobuf_Empty*(message: google_protobuf_Empty): uint64
+proc toJson*(message: google_protobuf_Empty): JsonNode
proc newgoogle_protobuf_Empty*(): google_protobuf_Empty =
new(result)
@@ -39,6 +43,9 @@ proc readgoogle_protobuf_Empty*(stream: ProtobufStream): google_protobuf_Empty =
raise newException(InvalidFieldNumberError, "Invalid field number: 0")
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_Empty): JsonNode =
+ result = newJObject()
+
proc serialize*(message: google_protobuf_Empty): string =
let
ss = newStringStream()
diff --git a/src/nimpb/wkt/field_mask_pb.nim b/src/nimpb/wkt/field_mask_pb.nim
index 23e125e..e925416 100644
--- a/src/nimpb/wkt/field_mask_pb.nim
+++ b/src/nimpb/wkt/field_mask_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
type
google_protobuf_FieldMask* = ref google_protobuf_FieldMaskObj
diff --git a/src/nimpb/wkt/source_context_pb.nim b/src/nimpb/wkt/source_context_pb.nim
index 6cc19af..815da98 100644
--- a/src/nimpb/wkt/source_context_pb.nim
+++ b/src/nimpb/wkt/source_context_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
type
google_protobuf_SourceContext* = ref google_protobuf_SourceContextObj
@@ -16,6 +19,7 @@ proc newgoogle_protobuf_SourceContext*(data: string): google_protobuf_SourceCont
proc writegoogle_protobuf_SourceContext*(stream: ProtobufStream, message: google_protobuf_SourceContext)
proc readgoogle_protobuf_SourceContext*(stream: ProtobufStream): google_protobuf_SourceContext
proc sizeOfgoogle_protobuf_SourceContext*(message: google_protobuf_SourceContext): uint64
+proc toJson*(message: google_protobuf_SourceContext): JsonNode
proc newgoogle_protobuf_SourceContext*(): google_protobuf_SourceContext =
new(result)
@@ -66,6 +70,11 @@ proc readgoogle_protobuf_SourceContext*(stream: ProtobufStream): google_protobuf
setfile_name(result, readString(stream))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_SourceContext): JsonNode =
+ result = newJObject()
+ if hasfile_name(message):
+ result["fileName"] = %message.file_name
+
proc serialize*(message: google_protobuf_SourceContext): string =
let
ss = newStringStream()
diff --git a/src/nimpb/wkt/struct_pb.nim b/src/nimpb/wkt/struct_pb.nim
index 73db617..2a38f6d 100644
--- a/src/nimpb/wkt/struct_pb.nim
+++ b/src/nimpb/wkt/struct_pb.nim
@@ -1,10 +1,13 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import tables
export tables
import nimpb/nimpb
+import nimpb/json as nimpb_json
type
google_protobuf_NullValue* {.pure.} = enum
diff --git a/src/nimpb/wkt/timestamp_pb.nim b/src/nimpb/wkt/timestamp_pb.nim
index bddbd55..5f00154 100644
--- a/src/nimpb/wkt/timestamp_pb.nim
+++ b/src/nimpb/wkt/timestamp_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
type
google_protobuf_Timestamp* = ref google_protobuf_TimestampObj
diff --git a/src/nimpb/wkt/type_pb.nim b/src/nimpb/wkt/type_pb.nim
index 153f257..efb7d26 100644
--- a/src/nimpb/wkt/type_pb.nim
+++ b/src/nimpb/wkt/type_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
import nimpb/wkt/any_pb
import nimpb/wkt/source_context_pb
@@ -88,30 +91,35 @@ proc newgoogle_protobuf_Option*(data: string): google_protobuf_Option
proc writegoogle_protobuf_Option*(stream: ProtobufStream, message: google_protobuf_Option)
proc readgoogle_protobuf_Option*(stream: ProtobufStream): google_protobuf_Option
proc sizeOfgoogle_protobuf_Option*(message: google_protobuf_Option): uint64
+proc toJson*(message: google_protobuf_Option): JsonNode
proc newgoogle_protobuf_Field*(): google_protobuf_Field
proc newgoogle_protobuf_Field*(data: string): google_protobuf_Field
proc writegoogle_protobuf_Field*(stream: ProtobufStream, message: google_protobuf_Field)
proc readgoogle_protobuf_Field*(stream: ProtobufStream): google_protobuf_Field
proc sizeOfgoogle_protobuf_Field*(message: google_protobuf_Field): uint64
+proc toJson*(message: google_protobuf_Field): JsonNode
proc newgoogle_protobuf_Type*(): google_protobuf_Type
proc newgoogle_protobuf_Type*(data: string): google_protobuf_Type
proc writegoogle_protobuf_Type*(stream: ProtobufStream, message: google_protobuf_Type)
proc readgoogle_protobuf_Type*(stream: ProtobufStream): google_protobuf_Type
proc sizeOfgoogle_protobuf_Type*(message: google_protobuf_Type): uint64
+proc toJson*(message: google_protobuf_Type): JsonNode
proc newgoogle_protobuf_EnumValue*(): google_protobuf_EnumValue
proc newgoogle_protobuf_EnumValue*(data: string): google_protobuf_EnumValue
proc writegoogle_protobuf_EnumValue*(stream: ProtobufStream, message: google_protobuf_EnumValue)
proc readgoogle_protobuf_EnumValue*(stream: ProtobufStream): google_protobuf_EnumValue
proc sizeOfgoogle_protobuf_EnumValue*(message: google_protobuf_EnumValue): uint64
+proc toJson*(message: google_protobuf_EnumValue): JsonNode
proc newgoogle_protobuf_Enum*(): google_protobuf_Enum
proc newgoogle_protobuf_Enum*(data: string): google_protobuf_Enum
proc writegoogle_protobuf_Enum*(stream: ProtobufStream, message: google_protobuf_Enum)
proc readgoogle_protobuf_Enum*(stream: ProtobufStream): google_protobuf_Enum
proc sizeOfgoogle_protobuf_Enum*(message: google_protobuf_Enum): uint64
+proc toJson*(message: google_protobuf_Enum): JsonNode
proc newgoogle_protobuf_Option*(): google_protobuf_Option =
new(result)
@@ -189,6 +197,13 @@ proc readgoogle_protobuf_Option*(stream: ProtobufStream): google_protobuf_Option
setvalue(result, newgoogle_protobuf_Any(data))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_Option): JsonNode =
+ result = newJObject()
+ if hasname(message):
+ result["name"] = %message.name
+ if hasvalue(message):
+ result["value"] = toJson(message.value)
+
proc serialize*(message: google_protobuf_Option): string =
let
ss = newStringStream()
@@ -491,6 +506,32 @@ proc readgoogle_protobuf_Field*(stream: ProtobufStream): google_protobuf_Field =
setdefault_value(result, readString(stream))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_Field): JsonNode =
+ result = newJObject()
+ if haskind(message):
+ result["kind"] = %($message.kind)
+ if hascardinality(message):
+ result["cardinality"] = %($message.cardinality)
+ if hasnumber(message):
+ result["number"] = %message.number
+ if hasname(message):
+ result["name"] = %message.name
+ if hastype_url(message):
+ result["typeUrl"] = %message.type_url
+ if hasoneof_index(message):
+ result["oneofIndex"] = %message.oneof_index
+ if haspacked(message):
+ result["packed"] = %message.packed
+ if hasoptions(message):
+ let arr = newJArray()
+ for value in message.options:
+ add(arr, toJson(value))
+ result["options"] = arr
+ if hasjson_name(message):
+ result["jsonName"] = %message.json_name
+ if hasdefault_value(message):
+ result["defaultValue"] = %message.default_value
+
proc serialize*(message: google_protobuf_Field): string =
let
ss = newStringStream()
@@ -699,6 +740,30 @@ proc readgoogle_protobuf_Type*(stream: ProtobufStream): google_protobuf_Type =
setsyntax(result, readEnum[google_protobuf_Syntax](stream))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_Type): JsonNode =
+ result = newJObject()
+ if hasname(message):
+ result["name"] = %message.name
+ if hasfields(message):
+ let arr = newJArray()
+ for value in message.fields:
+ add(arr, toJson(value))
+ result["fields"] = arr
+ if hasoneofs(message):
+ let arr = newJArray()
+ for value in message.oneofs:
+ add(arr, %value)
+ result["oneofs"] = arr
+ if hasoptions(message):
+ let arr = newJArray()
+ for value in message.options:
+ add(arr, toJson(value))
+ result["options"] = arr
+ if hassource_context(message):
+ result["sourceContext"] = toJson(message.source_context)
+ if hassyntax(message):
+ result["syntax"] = %($message.syntax)
+
proc serialize*(message: google_protobuf_Type): string =
let
ss = newStringStream()
@@ -819,6 +884,18 @@ proc readgoogle_protobuf_EnumValue*(stream: ProtobufStream): google_protobuf_Enu
addoptions(result, newgoogle_protobuf_Option(data))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_EnumValue): JsonNode =
+ result = newJObject()
+ if hasname(message):
+ result["name"] = %message.name
+ if hasnumber(message):
+ result["number"] = %message.number
+ if hasoptions(message):
+ let arr = newJArray()
+ for value in message.options:
+ add(arr, toJson(value))
+ result["options"] = arr
+
proc serialize*(message: google_protobuf_EnumValue): string =
let
ss = newStringStream()
@@ -997,6 +1074,25 @@ proc readgoogle_protobuf_Enum*(stream: ProtobufStream): google_protobuf_Enum =
setsyntax(result, readEnum[google_protobuf_Syntax](stream))
else: readUnknownField(stream, tag, result.unknownFields)
+proc toJson*(message: google_protobuf_Enum): JsonNode =
+ result = newJObject()
+ if hasname(message):
+ result["name"] = %message.name
+ if hasenumvalue(message):
+ let arr = newJArray()
+ for value in message.enumvalue:
+ add(arr, toJson(value))
+ result["enumvalue"] = arr
+ if hasoptions(message):
+ let arr = newJArray()
+ for value in message.options:
+ add(arr, toJson(value))
+ result["options"] = arr
+ if hassource_context(message):
+ result["sourceContext"] = toJson(message.source_context)
+ if hassyntax(message):
+ result["syntax"] = %($message.syntax)
+
proc serialize*(message: google_protobuf_Enum): string =
let
ss = newStringStream()
diff --git a/src/nimpb/wkt/wrappers_pb.nim b/src/nimpb/wkt/wrappers_pb.nim
index 296f5f4..d1b5f80 100644
--- a/src/nimpb/wkt/wrappers_pb.nim
+++ b/src/nimpb/wkt/wrappers_pb.nim
@@ -1,8 +1,11 @@
# Generated by protoc_gen_nim. Do not edit!
+import base64
import intsets
+import json
import nimpb/nimpb
+import nimpb/json as nimpb_json
type
google_protobuf_DoubleValue* = ref google_protobuf_DoubleValueObj
diff --git a/tests/conformance/conformance_nim.nim b/tests/conformance/conformance_nim.nim
index 9b30d26..461bc43 100644
--- a/tests/conformance/conformance_nim.nim
+++ b/tests/conformance/conformance_nim.nim
@@ -1,4 +1,5 @@
import endians
+import json
import streams
import strformat
@@ -27,7 +28,13 @@ proc myReadString(s: Stream, size: int): string =
raise newException(Exception, "failed to read data")
while true:
- var requestSize = readInt32Le(inputStream)
+ var requestSize = 0'i32
+
+ try:
+ requestSize = readInt32Le(inputStream)
+ except:
+ break
+
var requestData = myReadString(inputStream, requestSize)
let request = newConformance_ConformanceRequest(requestData)
@@ -36,19 +43,22 @@ while true:
if request.messageType == "protobuf_test_messages.proto2.TestAllTypesProto2":
response.skipped = "skipping proto2 tests"
- elif request.requestedOutputFormat == conformance_WireFormat.JSON:
- response.skipped = "dont know how to output json"
elif hasJsonPayload(request):
response.skipped = "dont know how to parse json"
else:
try:
let parsed = newprotobuf_test_messages_proto3_TestAllTypesProto3(string(request.protobufPayload))
- let ser = serialize(parsed)
- response.protobufPayload = bytes(ser)
+ if request.requestedOutputFormat == conformance_WireFormat.PROTOBUF:
+ let ser = serialize(parsed)
+ response.protobufPayload = bytes(ser)
+ elif request.requestedOutputFormat == conformance_WireFormat.JSON:
+ response.jsonPayload = $toJson(parsed)
except IOError as exc:
response.parse_error = exc.msg
except ParseError as exc:
response.parse_error = exc.msg
+ except ValueError as exc:
+ response.serializeError = exc.msg
except Exception as exc:
response.runtimeError = exc.msg
diff --git a/tests/conformance/failures.txt b/tests/conformance/failures.txt
new file mode 100644
index 0000000..5e8f520
--- /dev/null
+++ b/tests/conformance/failures.txt
@@ -0,0 +1,18 @@
+
+CONFORMANCE TEST BEGIN ====================================
+
+ERROR, test=Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.DOUBLE.JsonOutput: Output was not equivalent to reference message: modified: optional_double: 2.2250738585072014e-308 -> 2.2250738585072009e-308
+. request=protobuf_payload: "a\232\231\231\231\231\231\271?a\377\377\377\377\377\377\357\177a\000\000\000\000\000\000\020\000" requested_output_format: JSON message_type: "protobuf_test_messages.proto3.TestAllTypesProto3", response=json_payload: "{\"optionalDouble\":2.225073858507201e-308}"
+ERROR, test=Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.JsonOutput: JSON output we received from test was unparseable. request=protobuf_payload: "\321\002\232\231\231\231\231\231\271?\321\002\377\377\377\377\377\377\357\177\321\002\000\000\000\000\000\000\020\000" requested_output_format: JSON message_type: "protobuf_test_messages.proto3.TestAllTypesProto3", response=json_payload: "{\"repeatedDouble\":[0.1,1.797693134862316e+308,2.225073858507201e-308]}"
+WARNING, test=Recommended.FieldMaskPathsDontRoundTrip.JsonOutput: Should have failed to serialize, but didn't. request=protobuf_payload: "\372\022\010\n\006fooBar" requested_output_format: JSON message_type: "protobuf_test_messages.proto3.TestAllTypesProto3", response=json_payload: "{\"optionalFieldMask\":\"fooBar\"}"
+WARNING, test=Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput: Should have failed to serialize, but didn't. request=protobuf_payload: "\372\022\013\n\tfoo_3_bar" requested_output_format: JSON message_type: "protobuf_test_messages.proto3.TestAllTypesProto3", response=json_payload: "{\"optionalFieldMask\":\"foo_3_bar\"}"
+WARNING, test=Recommended.FieldMaskTooManyUnderscore.JsonOutput: Should have failed to serialize, but didn't. request=protobuf_payload: "\372\022\n\n\010foo__bar" requested_output_format: JSON message_type: "protobuf_test_messages.proto3.TestAllTypesProto3", response=json_payload: "{\"optionalFieldMask\":\"foo__bar\"}"
+
+These tests failed. If they can't be fixed right now, you can add them to the failure list so the overall suite can succeed. Add them to the failure list by running:
+ ./update_failure_list.py --add failing_tests.txt
+
+ Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.DOUBLE.JsonOutput
+ Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.JsonOutput
+
+CONFORMANCE SUITE FAILED: 249 successes, 563 skipped, 0 expected failures, 2 unexpected failures.
+