protected final <EB extends ExtendableBuilder<?, EB>>
  void readExtensions(EB msg, JsonParser par) throws IOException {
    @SuppressWarnings("unchecked")
    Set<OpenRtbJsonExtReader<EB>> extReaders = factory.getReaders((Class<EB>) msg.getClass());
    if (extReaders.isEmpty()) {
      par.skipChildren();
      return;
    }

    startObject(par);
    JsonToken tokLast = par.getCurrentToken();
    JsonLocation locLast = par.getCurrentLocation();

    while (true) {
      boolean extRead = false;
      for (OpenRtbJsonExtReader<EB> extReader : extReaders) {
        if (extReader.filter(par)) {
          extReader.read(msg, par);
          JsonToken tokNew = par.getCurrentToken();
          JsonLocation locNew = par.getCurrentLocation();
          boolean advanced = tokNew != tokLast || !locNew.equals(locLast);
          extRead |= advanced;

          if (!endObject(par)) {
            return;
          } else if (advanced && par.getCurrentToken() != JsonToken.FIELD_NAME) {
            tokLast = par.nextToken();
            locLast = par.getCurrentLocation();
          } else {
            tokLast = tokNew;
            locLast = locNew;
          }
        }
      }

      if (!endObject(par)) {
        // Can't rely on this exit condition inside the for loop because no readers may filter.
        return;
      }

      if (!extRead) {
        // No field was consumed by any reader, so we need to skip the field to make progress.
        if (logger.isDebugEnabled()) {
          logger.debug("Extension field not consumed by any reader, skipping: {} @{}:{}",
              par.getCurrentName(), locLast.getLineNr(), locLast.getCharOffset());
        }
        par.nextToken();
        par.skipChildren();
        tokLast = par.nextToken();
        locLast = par.getCurrentLocation();
      }
      // Else loop, try all readers again
    }
  }
protected final < EB extends ExtendableBuilder < ? , EB > > void readExtensions ( EB msg , JsonParser par ) throws IOException { @ SuppressWarnings ( "unchecked" ) Set < OpenRtbJsonExtReader < EB > > extReaders = factory . getReaders ( ( Class < EB > ) msg . getClass ( ) ) ; if ( extReaders . isEmpty ( ) ) { par . skipChildren ( ) ; return ; } startObject ( par ) ; JsonToken tokLast = par . getCurrentToken ( ) ; JsonLocation locLast = par . getCurrentLocation ( ) ; while ( true ) { boolean extRead = false ; for ( OpenRtbJsonExtReader < EB > extReader : extReaders ) { if ( extReader . filter ( par ) ) { extReader . read ( msg , par ) ; JsonToken tokNew = par . getCurrentToken ( ) ; JsonLocation locNew = par . getCurrentLocation ( ) ; boolean advanced = tokNew != tokLast || ! locNew . equals ( locLast ) ; extRead |= advanced ; if ( ! endObject ( par ) ) { return ; } else if ( advanced && par . getCurrentToken ( ) != JsonToken . FIELD_NAME ) { tokLast = par . nextToken ( ) ; locLast = par . getCurrentLocation ( ) ; } else { tokLast = tokNew ; locLast = locNew ; } } } if ( ! endObject ( par ) ) { return ; } if ( ! extRead ) { if ( logger . isDebugEnabled ( ) ) { logger . debug ( "Extension field not consumed by any reader, skipping: {} @{}:{}" , par . getCurrentName ( ) , locLast . getLineNr ( ) , locLast . getCharOffset ( ) ) ; } par . nextToken ( ) ; par . skipChildren ( ) ; tokLast = par . nextToken ( ) ; locLast = par . getCurrentLocation ( ) ; } } }
Read any extensions that may exist in a message.

@param msg Builder of a message that may contain extensions
@param par The JSON parser, positioned at the "ext" field
@param <EB> Type of message builder being constructed
@throws IOException any parsing error