Skip to content

Commit a53150d

Browse files
committed
feat: emit only nameIdentifier on creators[].nameIdentifiers[] (0.9.2)
Stop writing nameIdentifierScheme and schemeURI onto name identifiers; the schema requires only nameIdentifier and both derive from the identifier URL. ORCID detection and dedup now key off the orcid.org URL (orcid.py, identifiers.py, extract.py), so name + affiliation ORCID enrichment is unchanged.
1 parent 4768d31 commit a53150d

5 files changed

Lines changed: 29 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.9.2] - 2026-06-05
9+
10+
### Changed
11+
12+
- **`creators[].nameIdentifiers[]` now carry only `nameIdentifier`.** poster2json no longer writes `nameIdentifierScheme` or `schemeURI` onto name identifiers. The schema requires only `nameIdentifier`, and both fields are derivable from the identifier URL downstream. ORCID detection and dedup now key off the `orcid.org` URL instead of the scheme field, so name + affiliation ORCID enrichment is unchanged. Any scheme/schemeURI the model emits on name identifiers is stripped.
13+
814
## [0.9.1] - 2026-06-05
915

1016
### Fixed

poster2json/extract.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1946,7 +1946,10 @@ def _needs_orcid_enrichment(creators) -> bool:
19461946
if not has_aff:
19471947
continue
19481948
has_orcid = any(
1949-
isinstance(ni, dict) and ni.get("nameIdentifierScheme") == "ORCID"
1949+
isinstance(ni, dict) and (
1950+
ni.get("nameIdentifierScheme") == "ORCID"
1951+
or "orcid.org" in str(ni.get("nameIdentifier", "")).lower()
1952+
)
19501953
for ni in c.get("nameIdentifiers") or []
19511954
)
19521955
if not has_orcid:

poster2json/identifiers.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -235,18 +235,15 @@ def _enrich_existing_identifiers(data: dict) -> dict:
235235
if not isinstance(ni, dict):
236236
continue
237237
value = ni.get("nameIdentifier", "")
238-
result = infer_identifier_scheme(value)
239-
if result:
240-
scheme, uri = result
241-
if "nameIdentifierScheme" not in ni or not ni["nameIdentifierScheme"]:
242-
ni["nameIdentifierScheme"] = scheme
243-
if "schemeURI" not in ni or not ni["schemeURI"]:
244-
ni["schemeURI"] = uri
245-
# Fix 1: bare ORCIDs -> full URL format
246-
if scheme == "ORCID":
247-
m = ORCID_RE.search(value)
248-
if m and not value.startswith("http"):
249-
ni["nameIdentifier"] = f"https://orcid.org/{m.group(1)}"
238+
# nameIdentifiers carry only `nameIdentifier`; drop any scheme /
239+
# schemeURI the model emitted (schema requires only nameIdentifier).
240+
ni.pop("nameIdentifierScheme", None)
241+
ni.pop("schemeURI", None)
242+
# Normalize a bare ORCID to full URL form.
243+
if isinstance(value, str):
244+
m = ORCID_RE.search(value)
245+
if m and not value.startswith("http"):
246+
ni["nameIdentifier"] = f"https://orcid.org/{m.group(1)}"
250247

251248
# creators[*].affiliation[*].affiliationIdentifier -- normalize bare ROR IDs
252249
for creator in data.get("creators", []):
@@ -358,8 +355,6 @@ def _add_extracted_identifiers(
358355
creators[i].setdefault("nameIdentifiers", [])
359356
creators[i]["nameIdentifiers"].append({
360357
"nameIdentifier": f"https://orcid.org/{orcid}",
361-
"nameIdentifierScheme": "ORCID",
362-
"schemeURI": "https://orcid.org",
363358
})
364359
else:
365360
# Attach all to first creator
@@ -368,8 +363,6 @@ def _add_extracted_identifiers(
368363
for orcid in new_orcids:
369364
creators[0]["nameIdentifiers"].append({
370365
"nameIdentifier": f"https://orcid.org/{orcid}",
371-
"nameIdentifierScheme": "ORCID",
372-
"schemeURI": "https://orcid.org",
373366
})
374367

375368
# --- Crossref Funder IDs → fundingReferences[*].funderIdentifier ---

poster2json/orcid.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,14 @@ def lookup(
198198

199199
def _creator_has_orcid(creator: dict) -> bool:
200200
for ni in creator.get("nameIdentifiers", []):
201-
if isinstance(ni, dict) and ni.get("nameIdentifierScheme") == "ORCID":
201+
if not isinstance(ni, dict):
202+
continue
203+
# Detect by the identifier URL, since we no longer write
204+
# nameIdentifierScheme onto nameIdentifiers.
205+
if ni.get("nameIdentifierScheme") == "ORCID":
206+
return True
207+
nid = ni.get("nameIdentifier", "")
208+
if isinstance(nid, str) and "orcid.org" in nid.lower():
202209
return True
203210
return False
204211

@@ -234,11 +241,7 @@ def enrich_creators_orcid(creators: list, client: OrcidClient) -> list:
234241
continue
235242
creator.setdefault("nameIdentifiers", [])
236243
creator["nameIdentifiers"].append(
237-
{
238-
"nameIdentifier": f"https://orcid.org/{orcid}",
239-
"nameIdentifierScheme": "ORCID",
240-
"schemeURI": "https://orcid.org",
241-
}
244+
{"nameIdentifier": f"https://orcid.org/{orcid}"}
242245
)
243246
return creators
244247

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tool.poetry]
22

33
name = "poster2json"
4-
version = "0.9.1"
4+
version = "0.9.2"
55
description = "Convert scientific posters (PDF/images) to structured JSON metadata using Large Language Models"
66

77
packages = [{ include = "poster2json" }]

0 commit comments

Comments
 (0)