@@ -213,12 +213,16 @@ api.expand = async ({
213213 // set the type-scoped context to the context on input, for use later
214214 typeScopedContext = activeCtx ;
215215
216+ // Remember the first key found expanding to @type
217+ let typeKey = null ;
218+
216219 // look for scoped contexts on `@type`
217220 for ( const key of keys ) {
218221 const expandedProperty = _expandIri ( activeCtx , key , { vocab : true } , options ) ;
219222 if ( expandedProperty === '@type' ) {
220223 // set scoped contexts from @type
221224 // avoid sorting if possible
225+ typeKey = typeKey || key ;
222226 const value = element [ key ] ;
223227 const types =
224228 Array . isArray ( value ) ?
@@ -248,6 +252,7 @@ api.expand = async ({
248252 options,
249253 insideList,
250254 typeScopedContext,
255+ typeKey,
251256 expansionMap} ) ;
252257
253258 // get property count on expanded output
@@ -283,7 +288,10 @@ api.expand = async ({
283288 const types = _getValues ( rval , '@type' ) ;
284289
285290 // drop null @values unless custom mapped
286- if ( values . length === 0 ) {
291+ if ( _processingMode ( activeCtx , 1.1 ) && types . includes ( '@json' ) &&
292+ types . length === 1 ) {
293+ // Any value of @value is okay if @type: @json
294+ } else if ( values . length === 0 ) {
287295 const mapped = await expansionMap ( {
288296 unmappedValue : rval ,
289297 activeCtx,
@@ -304,9 +312,6 @@ api.expand = async ({
304312 'Invalid JSON-LD syntax; only strings may be language-tagged.' ,
305313 'jsonld.SyntaxError' ,
306314 { code : 'invalid language-tagged value' , element : rval } ) ;
307- } else if ( _processingMode ( activeCtx , 1.1 ) && types . includes ( '@json' ) &&
308- types . length === 1 ) {
309- // Any value of @value is okay if @type: @json
310315 } else if ( ! types . every ( t =>
311316 ( _isAbsoluteIri ( t ) && ! ( _isString ( t ) && t . indexOf ( '_:' ) === 0 ) ||
312317 _isEmptyObject ( t ) ) ) ) {
@@ -402,11 +407,20 @@ async function _expandObject({
402407 options = { } ,
403408 insideList,
404409 typeScopedContext,
410+ typeKey,
405411 expansionMap
406412} ) {
407413 const keys = Object . keys ( element ) . sort ( ) ;
408414 const nests = [ ] ;
409415 let unexpandedValue ;
416+
417+ // Remember inputType to aid with JSON literals
418+ let inputType = element [ typeKey ] ;
419+ if ( inputType ) {
420+ inputType = _asArray ( inputType ) . slice ( - 1 ) [ 0 ] ;
421+ inputType = _expandIri ( activeCtx , inputType , { vocab : true } , options ) ;
422+ }
423+
410424 for ( const key of keys ) {
411425 let value = element [ key ] ;
412426 let expandedValue ;
@@ -517,8 +531,13 @@ async function _expandObject({
517531 // capture value for later
518532 // "colliding keywords" check prevents this from being set twice
519533 unexpandedValue = value ;
520- _addValue (
521- expandedParent , '@value' , value , { propertyIsArray : options . isFrame } ) ;
534+ if ( inputType === '@json' && _processingMode ( activeCtx , 1.1 ) ) {
535+ // no coercion to array, and retain all values
536+ expandedParent [ '@value' ] = value ;
537+ } else {
538+ _addValue (
539+ expandedParent , '@value' , value , { propertyIsArray : options . isFrame } ) ;
540+ }
522541 continue ;
523542 }
524543
@@ -803,6 +822,7 @@ async function _expandObject({
803822 expandedParent,
804823 options,
805824 insideList,
825+ typeKey,
806826 expansionMap} ) ;
807827 }
808828 }
0 commit comments