google/openrtb

problem parsing json for request that contain 'native' key

avitaleli opened this issue · 5 comments

Hi,

While trying to add support for open RTB 2.3 I would like to support native adds, I took an example of native ad request from the specification document:

{  
   "id":"80ce30c53c16e6ede735f123ef6e32361bfc7b22",
   "at":1,
   "cur":[  
      "USD"
   ],
   "imp":[  
      {  
         "id":"1",
         "bidfloor":0.03,
         "native":{  
            "request":"...Native Spec request as an encoded string...",
            "ver":"1.0",
            "api":[  
               3
            ],
            "battr":[  
               13,
               14
            ]
         }
      }
   ],
   "site":{  
      "id":"102855"      "cat":[  
         "IAB3-1"
      ],
      "domain":"www.foobar.com",
      "page":"http://www.foobar.com/1234.html ",
      "publisher":{  
         "id":"8953",
         "name":"foobar.com",
         "cat":[  
            "IAB3-1"
         ],
         "domain":"foobar.com"
      }
   },
   "device":{  
      "ua":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13 
(KHTML, like Gecko) Version/5.1.7 Safari/534.57.2",
      "ip":"123.145.167.10"
   },
   "user":{  
      "id":"55816b39711f9b5acf3b90e313ed29e51665623f"
   }

Reading the message model in openrtb.proto I noticed:

message Native {
      oneof request_oneof {
        // Request payload complying with the Native Ad Specification.
        // Exactly one of {request, request_native} should be used;
        // this is the OpenRTB-compliant field for JSON serialization.
        // [AdX: BidRequest.AdSlot.NativeAdTemplate]
        string request = 1;

        // Request payload complying with the Native Ad Specification.
        // Exactly one of {request, request_native} should be used;
        // this is an alternate field preferred for Protobuf serialization.
        // [AdX: BidRequest.AdSlot.NativeAdTemplate]
        NativeRequest request_native = 50;
      }
      ...
}

I understand that the native object should contain either a string with the field request or the object NativeRequest

But when I run the request I get the error:

com.fasterxml.jackson.core.JsonParseException: Unexpected character ('.' (code 46)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
at [Source: java.io.CharArrayReader@3a9fcbdf; line: 1, column: 2]

From debugging the code I saw the following:
In class OpenRtbJsonReader::protected void readNativeField(JsonParser par, Native.Builder nativ, String fieldName) there is a switch case and for the possible fields and there is only request which is set as NativeRequest and not as a string as mentioned in the proto (also, the object itself which is generated by protobuf has a string field for request and a NativeRequest objects from request_native. Therefore the string

...Native Spec request as an encoded string...

which is set in the request can't be set to the OpenRTB.BidRequest object.

Can you please help me what I am doing wrong? or maybe there is some bug? I can't get it working with a native request to my server.

Thank you.

The example you find in the spec uses this string "...Native Spec etc." only as a placeholder, that string is not valid native request content, so the parsing failure you see is correct. This string must contain an encoded JSON object, for example {\"ver\":\"1.0\"} is a minimal valid native request (already escaped to be inserted into the larger JSON BidRequest).

Hi @opinali,

Thank you for your answer. I would appreciate if you can explain me what means the following in the .proto:

message Native {
      oneof request_oneof {
        // Request payload complying with the Native Ad Specification.
        // Exactly one of {request, request_native} should be used;
        // this is the OpenRTB-compliant field for JSON serialization.
        // [AdX: BidRequest.AdSlot.NativeAdTemplate]
        string request = 1;

        // Request payload complying with the Native Ad Specification.
        // Exactly one of {request, request_native} should be used;
        // this is an alternate field preferred for Protobuf serialization.
        // [AdX: BidRequest.AdSlot.NativeAdTemplate]
        NativeRequest request_native = 50;
      }
      ...
}

Doesn't it mean that you can have either one of request as a string, or request_native as an object?

Thanks again.

Hi @opinali

I followed your example and set the following

{"id":"80ce30c53c16e6ede735f123ef6e32361bfc7b22","at":1,"cur":["USD"],"imp":[{"id":"1","bidfloor":0.03,"native":{"request":{"ver":"1.0"},"ver":"1.0","api":[3],"battr":[13,14]}}],"site":{"id":"102855","cat":["IAB3-1"],"domain":"www.foobar.com","page":"http://www.foobar.com/1234.html","publisher":{"id":"8953","name":"foobar.com","cat":["IAB3-1"],"domain":"foobar.com"}},"device":{"ua":"Mozilla/5.0(Macintosh;IntelMacOSX10_6_8)AppleWebKit/537.13(KHTML,likeGecko)Version/5.1.7Safari/534.57.2","ip":"123.145.167.10"},"user":{"id":"55816b39711f9b5acf3b90e313ed29e51665623f"}}

But the d-serialization fails with an exception:

com.fasterxml.jackson.core.JsonParseException: Unexpected end-of-input: expected close marker for OBJECT (from [Source: java.io.CharArrayReader@5d70dd3d; line: 1, column: 1])
at [Source: java.io.CharArrayReader@5d70dd3d; line: 1, column: 3]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1586)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:521)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportInvalidEOF(ParserMinimalBase.java:458)
at com.fasterxml.jackson.core.base.ParserBase._handleEOF(ParserBase.java:532)
at com.fasterxml.jackson.core.base.ParserBase._eofAsNextChar(ParserBase.java:540)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._skipWSOrEnd(ReaderBasedJsonParser.java:2265)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:601)
at com.google.openrtb.json.OpenRtbJsonUtils.startObject(OpenRtbJsonUtils.java:53)

Please help me to figure out why there is a problem with my JSON, I don't manage to find whether I can work with native.

Thank you.

Hi @elic9,

In OpenRTB Native 1.0 the imp.native field is included as a JSON-encoded string in the bid request.
It's the same for the native creative; it is returned as a JSON-encoded string in the adm field of the bid response.
While Native 1.0 supported only an encoded string, the current draft for 1.1 adds support for a direct object and encourages adoption of that option to reduce confusion.
Please have a look at http://www.iab.com/wp-content/uploads/2016/01/OpenRTB-Native-Ads-Specification-Draft.pdf chapter 4.1 and 5 for more information.

Like you I'm not really happy with it. Please have a look at my pull request #87 in which I try to fix/improve the behavior and prepare OpenRTB Native 1.1 compatibility.