@@ -200,6 +200,37 @@ def collapse_jsonld_context(cls, values):
200200 values .pop ("@context" , None )
201201 return values
202202
203+ @root_validator (pre = True )
204+ def fix_role_node_link (cls , values ):
205+ """roles aren't terribly well documented, but they appear to be done by linking
206+ a Role to a Person or Organization node with "@id" or "contributor"/"author". The
207+ Codemeta generator uses the key "schema:author" and "contributor", but it seems better
208+ to use the node @id that actually exists in a schema.org Role
209+
210+ see https://github.com/codemeta/codemeta/issues/240
211+ """
212+ KEYS = ["author" , "contributor" , "schema:author" , "schema:contributor" ]
213+
214+ def transform_role (role_item ):
215+ if isinstance (role_item , dict ) and (
216+ role_item .get ("type" ) == "Role" or role_item .get ("@type" ) == "Role"
217+ ):
218+ for key in KEYS :
219+ if key in role_item :
220+ role_item ["@id" ] = role_item .pop (key )
221+ break
222+ return role_item
223+
224+ for field in ["author" , "contributor" ]:
225+ if field in values :
226+ if isinstance (values [field ], list ):
227+ values [field ] = [
228+ transform_role (role_item ) for role_item in values [field ]
229+ ]
230+ else :
231+ values [field ] = transform_role (values [field ])
232+ return values
233+
203234 @root_validator (pre = True )
204235 def coalesce_embargo_end_date (cls , values ):
205236 embargo_date = values .get ("embargoDate" )
0 commit comments