Person
Generates a person, with names, a sex, a date of birth, a US race and ethnicity, and text values built from them.
Use it for a row that represents a person, such as a customer, an employee or a patient. Every mapped sub-field in a row describes the same person:
- The first name and middle names match the row's sex. In a country whose surnames have separate male
and female forms,
lastNamehas the form that matches it too. raceandethnicityare generated from the row's own first name and last name.- Every name in a row is from the same country, also when
countriescontains more than one. custom,derivedIdandderivedId2are built from the row's other values.
Separate Name and Date fields are generated independently of each other, so
none of this applies to them. Use Name for a column that contains a name on its own.
Sub-fields: at least one must be mapped. See Sub-fields.
Every JSON block on this page is a single field object, one entry in a table's fields array.
See Building a Request for the full request structure.
Sub-fields
A Person field has eleven sub-fields. Only the mapped sub-fields are generated, and at least one must be mapped.
| Sub-field | Example value | Description |
|---|---|---|
custom |
Hindle, Revel - DOB 1986-01-19 (Male) |
A text value built from the row's other sub-fields by customFormat. See customFormat. |
derivedId |
X-1986-1901-HINDL-5342 |
An identifier built from sections of the row's person. See derivedId. |
derivedId2 |
RHGN0685 |
A second identifier, built by the same rules from the same person. See derivedId2. |
dob |
1986-01-19 |
The date of birth. Must be mapped to a Date column. See Date of birth. |
ethnicity |
NonHispanic |
Hispanic or NonHispanic. US only. See Race and ethnicity. |
firstName |
Revel |
The first name. |
lastName |
Hindle |
The last name. In pl, cz, gr and ie, it has the form that matches the row's sex. |
middleName |
Robles |
A middle name, from the first-name or the last-name list. See Middle names. |
middleName2 |
Roswell |
A second middle name, with settings of its own. See Middle names. |
race |
White |
One of five race categories. US only. See Race and ethnicity. |
sex |
Male |
The generated sex, Male or Female, or M or F. See Sex. |
custom, derivedId and derivedId2 are built from the other sub-fields. A sub-field used in
customFormat, derivedId or derivedId2 is generated whether or not it is mapped, so an identifier can
contain a date of birth that is not a column of its own.
The name sub-fields and race, ethnicity and sex must be mapped to a text column such as VarChar.
Properties
| Property | Type | Default | Description |
|---|---|---|---|
countries |
NameCountryWeight[] |
none | The countries the names are from. Required unless dob is the only sub-field generated. See NameCountryWeight. |
customFormat |
string? |
none | The template for custom, such as "{lastName}, {firstName}". Required when custom is mapped. See customFormat. |
derivedId |
array? |
none | The sections of derivedId. Required when derivedId is mapped. See derivedId. |
derivedId2 |
array? |
none | The sections of derivedId2. Required when derivedId2 is mapped. See derivedId2. |
dobEnd |
string? (date) |
2006-12-31 |
The latest date of birth. The default applies only when dobMean is not set. See Date of birth. |
dobMean |
string? (date) |
none | The center of a normal distribution of dates of birth. See Date of birth. |
dobStart |
string? (date) |
1940-01-01 |
The earliest date of birth. The default applies only when dobMean is not set. See Date of birth. |
dobStdDev |
number? |
none | The standard deviation of the distribution, in days. Required when dobMean is set, and must be greater than 0. |
firstNameBeginsWith |
string[]? |
none | The first letters a first name can start with. See Name beginsWith. |
firstNameCaseOutput |
CaseOutput |
"None" |
The case of the first name. |
firstNameMaxLength |
integer? |
none | The maximum length of a first name. |
firstNameMinLength |
integer? |
none | The minimum length of a first name. |
firstNamePopularityMax |
number? |
none | The maximum popularity (0-100) of a first name. See Name popularityMax. |
firstNamePopularityMin |
number? |
none | The minimum popularity (0-100) of a first name. See Name popularityMin. |
firstNamePopularityRamp |
number |
0 |
How strongly the selection of a first name is weighted toward popular names (0-100). See Name popularityRamp. |
firstNameRaces |
NameRaceWeight[]? |
none | The race categories of the first names, weighted. US only. Replaces races for the first name. |
lastNameBeginsWith |
string[]? |
none | The first letters a last name can start with. |
lastNameCaseOutput |
CaseOutput |
"None" |
The case of the last name. |
lastNameMaxLength |
integer? |
none | The maximum length of a last name. |
lastNameMinLength |
integer? |
none | The minimum length of a last name. |
lastNamePopularityMax |
number? |
none | The maximum popularity (0-100) of a last name. |
lastNamePopularityMin |
number? |
none | The minimum popularity (0-100) of a last name. |
lastNamePopularityRamp |
number |
0 |
How strongly the selection of a last name is weighted toward popular names (0-100). |
lastNameRaces |
NameRaceWeight[]? |
none | The race categories of the last names, weighted. US only. Replaces races for the last name. |
map |
object |
required | Maps the sub-fields to destination columns. See Building a Request. |
middleName2CaseOutput |
CaseOutput |
"None" |
The case of the second middle name. |
middleName2PercentageFirstName |
number |
50 |
The percentage (0-100) of second middle names from the first-name list. |
middleName2PopularityMax |
number? |
none | The maximum popularity (0-100) of a second middle name. |
middleName2PopularityMin |
number? |
none | The minimum popularity (0-100) of a second middle name. |
middleName2PopularityRamp |
number |
0 |
How strongly the selection of a second middle name is weighted toward popular names (0-100). |
middleName2Races |
NameRaceWeight[]? |
none | The race categories of the second middle names, weighted. US only. Replaces races for the second middle name. |
middleNameCaseOutput |
CaseOutput |
"None" |
The case of the middle name. |
middleNamePercentageFirstName |
number |
50 |
The percentage (0-100) of middle names from the first-name list. The rest are from the last-name list. |
middleNamePopularityMax |
number? |
none | The maximum popularity (0-100) of a middle name. |
middleNamePopularityMin |
number? |
none | The minimum popularity (0-100) of a middle name. |
middleNamePopularityRamp |
number |
0 |
How strongly the selection of a middle name is weighted toward popular names (0-100). |
middleNameRaces |
NameRaceWeight[]? |
none | The race categories of the middle names, weighted. US only. Replaces races for the middle name. |
nullPercentageMax |
number |
0 |
Upper bound (0-100) of the percentage of rows that should be null. See nullPercentageMin. |
nullPercentageMin |
number |
0 |
Lower bound (0-100) of the percentage of rows that should be null. The rate is fixed once for the whole field from this range, not recalculated per row. Set equal to nullPercentageMax for an exact rate. A null row has every mapped sub-field empty. |
percentageMaleMax |
number |
50 |
Upper bound (0-100) of the percentage of rows with a male sex. See percentageMaleMin. |
percentageMaleMin |
number |
50 |
Lower bound (0-100) of the percentage of rows with a male sex. The percentage is fixed once for the whole field from this range, not recalculated per row. Set equal to percentageMaleMax for an exact split. |
races |
NameRaceWeight[]? |
none | The race categories of every name, weighted. US only. A name's own setting, such as firstNameRaces, replaces it for that name. |
seed |
integer |
random | Per-field seed, overriding the request's own seed for this field only. |
sex |
"Any" / "Male" / "Female" |
"Any" |
Limits every row to one sex without generating a sex value. Ignored when sex is mapped. See Sex. |
sexOutputFormat |
"FullWord" / "Abbreviated" |
"FullWord" |
Male and Female, or M and F. See Sex. |
unique |
boolean |
false |
Whether every row must have a different combination of the mapped values. See Unique rows. |
Properties by sub-field
A property that applies only to a sub-field that is not generated has no effect.
| Sub-field | Properties |
|---|---|
custom |
customFormat |
derivedId |
derivedId |
derivedId2 |
derivedId2 |
dob |
dobEnd, dobMean, dobStart, dobStdDev |
firstName |
countries, firstNameBeginsWith, firstNameCaseOutput, firstNameMaxLength, firstNameMinLength, firstNamePopularityMax, firstNamePopularityMin, firstNamePopularityRamp, firstNameRaces, races, sex |
lastName |
countries, lastNameBeginsWith, lastNameCaseOutput, lastNameMaxLength, lastNameMinLength, lastNamePopularityMax, lastNamePopularityMin, lastNamePopularityRamp, lastNameRaces, races, sex |
middleName |
countries, middleNameCaseOutput, middleNamePercentageFirstName, middleNamePopularityMax, middleNamePopularityMin, middleNamePopularityRamp, middleNameRaces, races |
middleName2 |
countries, middleName2CaseOutput, middleName2PercentageFirstName, middleName2PopularityMax, middleName2PopularityMin, middleName2PopularityRamp, middleName2Races, races |
race, ethnicity |
countries |
sex |
percentageMaleMax, percentageMaleMin, sexOutputFormat |
map, nullPercentageMin, nullPercentageMax, seed and unique apply to the whole field.
A set of name filters that no name matches, such as a firstNameMinLength longer than every first name,
is rejected before any data is generated.
NameCountryWeight
countries contains one or more entries, with at most one entry per country:
| Property | Type | Default | Description |
|---|---|---|---|
country |
string |
required | A two-letter country code, such as us or pl. See GET /v1/names/countries for the countries available. |
weight |
number |
1 |
The country's weight relative to the other entries in the list. Must be greater than 0. |
greekScript |
boolean |
false |
Greek names in Greek script. gr only. See Name. |
japaneseScript |
"Romaji" / "Kanji" / "Hiragana" |
"Romaji" |
The script of Japanese names. jp only. See Name. |
koreanScript |
boolean |
false |
Korean names in Hangul. kr only. See Name. |
Weights are relative, not percentages, so they do not need to total any particular number. 3 and 1
give the same distribution as 30 and 10. With no weights set, every country is equally likely.
Each row is from one country, selected by weight, and every name in the row is from that country. Three quarters of these rows are from the US and one quarter from Poland:
{
"type": "Person",
"countries": [
{ "country": "us", "weight": 3 },
{ "country": "pl" }
],
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name |
|---|---|
| Mansour | Sierzputowski |
| Elunia | Pawul |
| Rachael | Hoffstatter |
| Ayumi | Steingart |
| Lukrecja | Słomczewski |
| Pelayo | Rushmore |
Middle names
middleName and middleName2 are each selected from either the country's first names or its last
names. middleNamePercentageFirstName and middleName2PercentageFirstName set the percentage from the
first-name list, and the rest are from the last-name list. A middle name from the last-name list is
typical of a family name used as a middle name.
The two middle names are selected separately, from their own settings. The firstName and lastName
settings do not apply to them.
When the row has a sex, from the sex sub-field or the sex property, a middle name from the
first-name list is a male or female name to match. In pl, cz, gr and ie, a middle name from the
last-name list has the matching form.
Race and ethnicity
race is one of five race categories: White, Black, AmericanIndianAlaskaNative,
AsianPacificIslander and TwoOrMoreRaces. ethnicity is Hispanic or NonHispanic.
Every US name has a percentage breakdown across these five categories and Hispanic. A row's race is
selected using the combined breakdown of its first name and its last name, so a name that is common in
a category makes that category more likely. ethnicity is selected separately from the same breakdown,
so a row can be Hispanic with any race.
races, firstNameRaces, lastNameRaces, middleNameRaces and middleName2Races limit which names are
used, by the category with the largest share of each name. Each contains { race, weight } entries, with
the five race categories and Hispanic. See Name for how the weights
work. races applies to every name, and a name's own setting replaces it for that name.
A name limited to one category still has percentages in the others, so a row with names limited to
Hispanic can have a NonHispanic ethnicity. See
Name.
race, ethnicity and the race filters require countries to contain exactly one entry, us. A list
with more than one entry is rejected, even when one of them is us.
Sex
sex is both a property and a sub-field.
The sex sub-field generates a sex for each row. The first name and the middle names match it, and
in pl, cz, gr and ie the last name has the matching form. Two properties apply:
percentageMaleMinandpercentageMaleMaxset the percentage of male rows. The percentage is fixed once for the whole field from that range. Set both to the same number for an exact split.sexOutputFormatwrites the value asMaleandFemale(FullWord, the default) orMandF(Abbreviated).
The sex property limits every row to Male or Female names without generating a value. It
applies to the first name and the middle names and, in pl, cz, gr and ie, to the last name. It is
ignored when the sex sub-field is mapped.
Date of birth
dob is generated in one of two ways:
- A range. Without
dobMean, every date fromdobStarttodobEndis equally likely. An unsetdobStartis1940-01-01and an unsetdobEndis2006-12-31. A range that is empty, such as adobEndearlier than the defaultdobStart, is rejected. - A distribution. With
dobMeanset, dates of birth have a normal distribution arounddobMean, with a standard deviation ofdobStdDevdays.dobStartanddobEndare optional and have no default. When set,dobMeanmust be within them.
mean, stdDev, min and max affect the output. The curve is the number of rows with each value. Most values are near mean, and fewer are further away, at a rate set by stdDev. A value beyond min or max is set to that boundary, shown by the solid bar at each one.mean sets the center and stdDev sets the width, both in the field's own units. About 68% of values
are within one stdDev of mean, about 95% within two, and about 99.7% within three. A larger
stdDev spreads the values further from mean, and a smaller one keeps them closer to it.
min and max are optional. Without them, a value can be any distance from mean within the range
the field supports. With them, a value outside the range is set to the nearer of min or max. It is
not generated again. The solid bars in the diagram are these values.
When the range is narrow relative to stdDev, many rows have a value of exactly min or max. In the
diagram, the range is one and a half standard deviations either side of mean. To reduce the number of
rows on the boundaries, widen the range or reduce stdDev.
For a date of birth, a dobStdDev of 3650 is about ten years, so about 95% of dates of birth are within
twenty years of dobMean.
customFormat
customFormat builds one text value from the row's other sub-fields, such as a display name.
{
"type": "Person",
"countries": [{ "country": "us" }],
"customFormat": "{lastName}, {firstName} - DOB {dob} ({sex})",
"dobStart": "1960-01-01",
"dobEnd": "2005-12-31",
"seed": 1,
"map": { "custom": { "column": "display", "dataType": "VarChar" } }
}
Sample output:
| display |
|---|
| Gaugh, Rory - DOB 1988-09-19 (Male) |
| Ocallaghan, Guinevere - DOB 1985-05-13 (Female) |
| Zigrang, Allysa - DOB 1994-04-08 (Female) |
| Cantoni, Jaswinder - DOB 1987-07-25 (Female) |
| Bregel, Resse - DOB 1965-08-10 (Female) |
Each {name} is replaced with that sub-field's value for the row. The names are firstName,
lastName, middleName, middleName2, dob, race, ethnicity and sex, and an unknown name is
rejected. A date is written as yyyy-MM-dd, and every other value as it would be written in its own
column. The rest of the template is written as it is.
{{ and }} write a literal brace, so "{{{firstName}}}" writes the first name inside braces. A {
that is not closed is rejected. These are the same rules as a calculated
Template.
A sub-field used in the template is generated whether or not it is mapped. In the example above, the
date of birth and the sex are part of display and are not columns of their own.
derivedId
derivedId builds an identifier from sections, written in the order given. A bare string is fixed text.
An object is a section with a source.
{
"type": "Person",
"countries": [{ "country": "us" }],
"dobStart": "1960-01-01",
"dobEnd": "2005-12-31",
"derivedId": [
"X-",
{ "source": "Dob", "part": "Year", "length": 4 },
"-",
{ "source": "Dob", "part": "Day", "length": 2 },
{ "source": "Dob", "part": "Month", "length": 2 },
"-",
{ "source": "LastName", "length": 5, "case": "Upper", "pad": "X" },
"-",
{ "source": "Number", "length": 4 }
],
"seed": 2,
"map": {
"lastName": { "column": "last_name", "dataType": "VarChar" },
"dob": { "column": "date_of_birth", "dataType": "Date" },
"derivedId": { "column": "person_id", "dataType": "VarChar" }
}
}
Sample output:
| last_name | date_of_birth | person_id |
|---|---|---|
| Verdi | 1969-10-11 | X-1969-1110-VERDI-3842 |
| Wilckens | 1962-07-30 | X-1962-3007-WILCK-0532 |
| Fritsch | 1990-05-22 | X-1990-2205-FRITS-3788 |
| Hribar | 1968-11-25 | X-1968-2511-HRIBA-6991 |
| Tree | 1984-05-14 | X-1984-1405-TREEX-2495 |
The identifier is X-, the year of birth, the day and the month of birth, the first five letters of the
last name in upper case, and four random digits. Tree has four letters, so pad adds an X to make TREEX. The day is before the month, so 1110 in the first row is October 11.
Sources
source |
Produces |
|---|---|
Checksum |
A check character for the digits before it. See Check characters. |
Dob |
The year, month or day of the date of birth, set by part. |
Ethnicity |
The generated ethnicity. |
FirstName |
The generated first name. |
LastName |
The generated last name. |
Letters |
length random letters from A to Z, in upper case unless case is set. |
Literal |
The text in value. A bare string is the same as a Literal section. |
Lookup |
One entry from lookupValues, selected by weight for each row. See Lookup sections. |
MiddleName |
The generated middle name. |
MiddleName2 |
The generated second middle name. |
Number |
length random digits, from 0 to 9. The first digit can be 0. |
Race |
The generated race. |
Sex |
The generated sex. |
FirstName, LastName, MiddleName, MiddleName2, Race, Ethnicity and Sex are the text sources.
Settings
| Setting | Applies to | Description |
|---|---|---|
add |
Dob |
A number added to the year, month or day. |
addWhenFemale |
Dob |
A number added when the row's sex is female, in addition to add. See Offsets. |
case |
text sources, Letters |
None, Upper, Lower or Proper. Applied last. Defaults to None. |
length |
every source except Literal, Lookup and Checksum |
The number of characters. Required for Dob, Number and Letters. Optional for a text source, which uses the whole value from start when it is not set. |
lookupValues |
Lookup |
The entries, each { value, weight }. Required, with at least one entry. |
method |
Checksum |
Luhn, Mod11 or Verhoeff. Required. See Check characters. |
pad |
text sources | A single character added to the right of a value shorter than length. Requires length. Defaults to no padding. |
part |
Dob |
Year, Month or Day. Required. |
phonetic |
FirstName, LastName, MiddleName, MiddleName2 |
None, Soundex, RefinedSoundex, Metaphone or Nysiis. Defaults to None. See Phonetic encoding. |
sanitize |
text sources | None, Ascii, Letters or LettersAndDigits. Applied first. Defaults to None. See Sanitizing a name. |
start |
text sources, Dob |
The position of the first character, counting from 1. Defaults to 1. See Widths. |
value |
Literal |
The text, written exactly as given. Required. |
A text section is processed in this order: sanitize, phonetic, start and length, pad, then
case.
A setting on a section it does not apply to is rejected, and the message identifies the section by its
position, such as derivedId section 3 (Literal): length has no meaning on a Literal, whose width is its own text.
Widths
Without start, a Dob section is padded on the left with zeros to length, and then only the
rightmost length digits are used. length: 2 on Year is the last two digits of the year, and
length: 2 on Month or Day is a two-digit month or day.
With start, the year is written with four digits and the month and day with two. The section starts at
start and contains length digits. start: 3 with length: 1 on Year is the third digit of the
year, 8 for 1986.
A text section starts at start and contains length characters, or the rest of the value when length
is not set. A character with an accent counts as one character, whether it is stored as one character
or as a letter and a separate accent. A value shorter than length is padded only when pad is set.
Without pad, the section is shorter than length. With pad set to X, a last name of Ng and a
length of 5 produce NgXXX, and NGXXX with case set to Upper.
Lookup sections
A Lookup section selects one entry from a weighted list for each row. Use it for a part of an
identifier that is not from the person, such as a mail domain or an office code.
{
"source": "Lookup",
"lookupValues": [
{ "value": "@example.com", "weight": 6 },
{ "value": "@example.net", "weight": 3 },
{ "value": "@example.org", "weight": 1 }
]
}
Weights are relative, so 6, 3 and 1 give the same distribution as 60, 30 and 10. An entry
with no weight has a weight of 1. Every weight must be greater than 0. An entry is written exactly as
given, so a Lookup section has no length.
Sanitizing a name
Names can contain accents, spaces, apostrophes, hyphens and letters from other scripts. sanitize
removes the characters an identifier cannot contain, such as in the local part of an email address.
sanitize |
Keeps | Ferreira-Gonçalves |
|---|---|---|
None |
Every character. The default. | Ferreira-Gonçalves |
Ascii |
ASCII characters, including punctuation and spaces, with accents removed. | Ferreira-Goncalves |
Letters |
The letters A to Z, with accents removed. | FerreiraGoncalves |
LettersAndDigits |
The letters A to Z and the digits 0 to 9, with accents removed. | FerreiraGoncalves |
With accents removed, José is Jose and Müller is Muller. A letter with a stroke or a ligature is
replaced with plain letters: Nørgaard is Norgaard, Łukasz is Lukasz, and ß, æ, œ and þ
are ss, ae, oe and th. Any other character outside the kept set is removed, so a name in another
script produces an empty value. Set pad to fill the section to its length.
Phonetic encoding
A phonetic encoding converts a name into a code based on its pronunciation, so that names that sound
alike can have the same code. phonetic is applied before start and length.
phonetic |
Produces | Whitfield |
|---|---|---|
Soundex |
The first letter and three digits, padded with zeros. | W314 |
RefinedSoundex |
The first letter and a digit for each letter, with repeated digits combined. | W062076 |
Metaphone |
Letters based on English pronunciation. 0 is the th sound and X is the sh sound. |
WTFLT |
Nysiis |
Letters produced by a fixed set of spelling rules for surnames. | WATFALD |
The code is not shortened, so use start and length to select part of it. A section with length: 1
on the last name followed by a section with phonetic: "Soundex" and start: 2 produces the Soundex
code.
Check characters
A Checksum section adds one check character, calculated from the digits before it in the identifier. A
system that validates the identifier calculates the check character again from the same digits and
rejects the identifier when the two are different. This detects most typing errors, such as a wrong
digit or two digits in the wrong order.
All three methods use only the digits 0 to 9 before the section, including digits in Literal and
Lookup sections, and ignore every other character. Letters from a name section do not change the
result. When there is no digit before the section, the check character is 0.
A Checksum section has no length, because a check character is always one character. It cannot be
the first section. Sections after it do not affect it.
method |
Check character | Detects any single wrong digit | Detects two adjacent digits swapped | Used by |
|---|---|---|---|---|
Luhn |
0 to 9 |
Yes | Yes, except a swap of 09 and 90 |
Payment card numbers, IMEI numbers |
Mod11 |
0 to 9, or X |
Yes, for up to nine digits | Yes | ISBN-10 |
Verhoeff |
0 to 9 |
Yes | Yes | Aadhaar numbers in India |
Luhn
- Starting with the rightmost digit before the check character and moving left, double every second digit. The rightmost digit is doubled, the one to its left is not, and so on.
- When doubling gives a number greater than 9, subtract 9 from it. This is the same as adding its two digits together, so 16 becomes 7.
- Add up all the digits, doubled and not doubled.
- The check digit is the amount that brings the total up to the next multiple of 10, or
0when the total is already a multiple of 10.
For 7992739871:
| Digit | 7 | 9 | 9 | 2 | 7 | 3 | 9 | 8 | 7 | 1 |
|---|---|---|---|---|---|---|---|---|---|---|
| Doubled | 18 | 4 | 6 | 16 | 2 | |||||
| Value added | 7 | 9 | 9 | 4 | 7 | 6 | 9 | 7 | 7 | 2 |
The total is 67. The next multiple of 10 is 70, so the check digit is 3 and the full number is
79927398713.
A swap of 0 and 9 is not detected because the pair adds 9 to the total in either order. A doubled
0 is still 0, and a doubled 9 is 18, which becomes 9.
Mod11
- Give each digit a weight. The rightmost digit before the check character has a weight of 2, the next digit to the left has a weight of 3, and so on.
- Multiply each digit by its weight and add the results.
- Divide the total by 11 and take the remainder.
- The check character is 11 minus the remainder. A result of 11 is written as
0, and a result of 10 is written asX.
For 030640615, the digits of the ISBN 0-306-40615-2 without its check character:
| Digit | 0 | 3 | 0 | 6 | 4 | 0 | 6 | 1 | 5 |
|---|---|---|---|---|---|---|---|---|---|
| Weight | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 |
| Product | 0 | 27 | 0 | 42 | 24 | 0 | 24 | 3 | 10 |
The total is 130. 130 divided by 11 is 11 with a remainder of 9, and 11 minus 9 is 2, so the check
character is 2. For 080442957 the total is 199, the remainder is 1, and 11 minus 1 is 10, so the
check character is X, giving the ISBN 0-8044-2957-X.
Every single wrong digit is detected for up to nine digits, which is the length ISBN-10 uses. With ten digits, the leftmost digit has a weight of 11. Any multiple of 11 leaves the remainder unchanged, so a wrong digit in that position is not detected. With more than ten digits, weights above 11 have the same effect as weights 11 lower, so a swap of two digits eleven positions apart is not detected either. A swap of two adjacent digits is detected at any length, because their weights always differ by 1.
Verhoeff
The Verhoeff method uses arithmetic based on the symmetries of a regular pentagon, a set of ten values with a multiplication table. Unlike ordinary addition, the result of combining two values in this table depends on their order. This is how the method detects every swap of two adjacent digits.
- Read the digits from right to left. The rightmost digit before the check character is position 1.
- Replace each digit with another digit using a substitution that depends on its position. The substitution repeats every eight positions.
- Combine the substituted digits one at a time, starting from 0, using the multiplication table.
- The check digit is the inverse of the final result in the same table. The same calculation over the full number, check digit included, gives 0.
The substitution and multiplication tables are the standard ones defined for the method. For 236:
| Position | Digit | Substituted digit | Result so far |
|---|---|---|---|
| 1 | 6 | 3 | 3 |
| 2 | 3 | 3 | 1 |
| 3 | 2 | 1 | 2 |
The final result is 2. Its inverse is 3, so the check digit is 3 and the full number is 2363.
See A member number with a check digit for a Verhoeff section in
a complete identifier.
Offsets
add adds a fixed number to the year, month or day. addWhenFemale adds a number only when the row's
sex is female. Some license number formats use this to include the sex in the month. With an
addWhenFemale of 50 on Month, January is 51 for a female row and 01 for a male row.
addWhenFemale generates a sex for each row whether or not sex is mapped. It works with either
sexOutputFormat.
derivedId2
derivedId2 is a second identifier, built by the same rules from the same person and mapped to its own
column. Everything in derivedId applies to it. Either one can be mapped without the other.
Use it for a person with two identifiers in different formats, such as an employee number and a login code.
{
"type": "Person",
"countries": [{ "country": "gb" }],
"derivedId": ["EMP-", { "source": "Number", "length": 6 }],
"derivedId2": [
{ "source": "FirstName", "length": 1, "case": "Upper" },
{ "source": "LastName", "length": 1, "case": "Upper" },
{ "source": "Letters", "length": 2 },
{ "source": "Number", "length": 4 }
],
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"derivedId": { "column": "employee_number", "dataType": "VarChar" },
"derivedId2": { "column": "login_code", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name | employee_number | login_code |
|---|---|---|---|
| John-Luke | Mohandas | EMP-643916 | JMAG3966 |
| Humza | Sherred | EMP-267790 | HSEJ7173 |
| Viansh | Eastgate | EMP-885760 | VEZU8055 |
| Dacia | Daish | EMP-296346 | DDRM2351 |
| Leif | Chegg | EMP-363190 | LCZM6012 |
The login code starts with the initials of the same first name and last name as the name columns.
Unique rows
With unique set, no two rows have the same combination of mapped values.
For some fields, the number of different values is calculated before any data is generated, and a request for more rows than that is rejected, stating how many are available:
- A field with only
firstNameor onlylastNamemapped, limited to the number of names that match its filters. - A field with only
derivedIdor onlyderivedId2mapped, when every section has a fixed number of values. ALiteralor aChecksumhas one value, aNumberoflength4 has 10,000, aLookuphas one value for each different entry, and aDobsection withoutstarthas the years fromdobStarttodobEnd, 12 months or 31 days. A text section, or aDobsection withstart, has no fixed number.
For any other field, a request that runs out of different values is rejected during generation.
Only Number, Letters and Lookup sections vary independently of the person. An identifier with none
of them is the same for two rows with the same name and date of birth.
Examples
Each example below is a single field object, one entry in a table's fields array within a full
request, not a complete request on its own. See Building a Request for how it fits
into a full DatasetRequest.
A first and last name
{
"type": "Person",
"countries": [{ "country": "us" }],
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name |
|---|---|
| Libertad | Hullinger |
| Rory | Brewbaker |
| Eliz | Cosco |
| Talmage | Juckett |
| Deondrea | Eaglin |
A generated sex with Polish surname forms
{
"type": "Person",
"countries": [{ "country": "pl" }],
"dobStart": "1960-01-01",
"dobEnd": "2005-12-31",
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"dob": { "column": "date_of_birth", "dataType": "Date" },
"sex": { "column": "sex", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name | date_of_birth | sex |
|---|---|---|---|
| Wojtek | Pełka | 1982-04-02 | Male |
| Mikael | Kotara | 1968-05-18 | Male |
| Filip | Naglik | 1975-03-16 | Male |
| Ulcia | Dziekańska | 1998-12-19 | Female |
| Sandi | Kwiatuszek | 1981-12-08 | Female |
| Jurij | Zapałowski | 1991-02-03 | Male |
Dziekańska is the female form of Dziekański, and Zapałowski is the male form of Zapałowska. Pełka, Kotara, Naglik and Kwiatuszek have one form for both sexes.
Names limited to one sex
With the sex property set and the sex sub-field not mapped, every row has female names and no sex
column.
{
"type": "Person",
"countries": [{ "country": "pl" }],
"sex": "Female",
"seed": 12,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name |
|---|---|
| Emka | Waśkowska |
| Anna Katarzyna | Kwapień |
| Lilly | Zimecka |
| Liana | Klinowska |
| Gaba | Chachaj |
| Malwinka | Gorynia |
Waśkowska, Zimecka and Klinowska are female forms. Kwapień, Chachaj and Gorynia have one form for both sexes.
A middle name, mostly from last names
{
"type": "Person",
"countries": [{ "country": "us" }],
"middleNamePercentageFirstName": 20,
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"middleName": { "column": "middle_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" }
}
}
Sample output:
| first_name | middle_name | last_name |
|---|---|---|
| Libertad | Amreen | Hullinger |
| Rory | Siena | Brewbaker |
| Eliz | Cenovia | Cosco |
| Talmage | Arizola | Juckett |
| Deondrea | Defenbaugh | Eaglin |
Two middle names from different lists
The first middle name is mostly from the first-name list and the second mostly from the last-name list.
{
"type": "Person",
"countries": [{ "country": "us" }],
"middleNamePercentageFirstName": 90,
"middleName2PercentageFirstName": 10,
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"middleName": { "column": "middle_name", "dataType": "VarChar" },
"middleName2": { "column": "middle_name_2", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" }
}
}
Sample output:
| first_name | middle_name | middle_name_2 | last_name |
|---|---|---|---|
| Libertad | Amreen | Richie | Hullinger |
| Rory | Shalandra | Horowitz | Brewbaker |
| Eliz | Cenovia | Bosques | Cosco |
| Talmage | Argel | Kunath | Juckett |
| Deondrea | Defenbaugh | Victo | Eaglin |
US race and ethnicity
{
"type": "Person",
"countries": [{ "country": "us" }],
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"race": { "column": "race", "dataType": "VarChar" },
"ethnicity": { "column": "ethnicity", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name | race | ethnicity |
|---|---|---|---|
| Romas | Ceglarek | White | NonHispanic |
| Javontae | Yuki | Black | NonHispanic |
| Brenetta | Murai | TwoOrMoreRaces | NonHispanic |
| Kahdijah | Trofa | Black | NonHispanic |
| Leilany | Platter | White | Hispanic |
| Ruger | Pietruszka | TwoOrMoreRaces | NonHispanic |
Dates of birth in a range
Every date from dobStart to dobEnd is equally likely.
{
"type": "Person",
"countries": [{ "country": "gb" }],
"dobStart": "1955-01-01",
"dobEnd": "2006-12-31",
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"dob": { "column": "date_of_birth", "dataType": "Date" }
}
}
Sample output:
| first_name | last_name | date_of_birth |
|---|---|---|
| John-Luke | Mohandas | 1986-10-07 |
| Humza | Sherred | 1983-09-20 |
| Viansh | Eastgate | 1963-05-19 |
| Dacia | Daish | 1982-07-25 |
| Leif | Chegg | 2004-11-27 |
Dates of birth around a mean
Dates of birth have a normal distribution around June 1, 1985, with a standard deviation of about ten years, from 1960 to 2004.
{
"type": "Person",
"countries": [{ "country": "us" }],
"dobMean": "1985-06-01",
"dobStdDev": 3650,
"dobStart": "1960-01-01",
"dobEnd": "2004-12-31",
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"dob": { "column": "date_of_birth", "dataType": "Date" }
}
}
Sample output:
| first_name | date_of_birth |
|---|---|
| Libertad | 1974-04-23 |
| Rory | 1991-05-31 |
| Eliz | 1982-03-10 |
| Talmage | 1981-10-24 |
| Deondrea | 1987-10-29 |
| Rashunda | 1984-11-07 |
Five of the six dates of birth are within ten years of dobMean.
A percentage of male rows
percentageMaleMin and percentageMaleMax set 80% male rows, and sexOutputFormat writes the sex as
M or F.
{
"type": "Person",
"countries": [{ "country": "us" }],
"percentageMaleMin": 80,
"percentageMaleMax": 80,
"sexOutputFormat": "Abbreviated",
"seed": 1,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"sex": { "column": "sex", "dataType": "Char" }
}
}
Sample output:
| first_name | sex |
|---|---|
| Rory | M |
| Talmage | M |
| Hernandez | M |
| Jaswinder | F |
| South | M |
| August | M |
| Mosi | M |
| Burrell | M |
| Kerwyn | M |
| Parichehr | F |
Null rows
{
"type": "Person",
"countries": [{ "country": "us" }],
"nullPercentageMin": 25,
"nullPercentageMax": 25,
"seed": 5,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" }
}
}
Sample output. A null row has every mapped sub-field empty:
| first_name | last_name |
|---|---|
| Catherine | Campagnola |
| Aurore | Esber |
| Muon | Rapant |
| Vagner | Brewin |
| Idiana | Lapsansky |
| Aril | Wimley |
A formatted record label
The template uses sub-fields that are not mapped. first_name and last_name are mapped for comparison
with the label, and the middle name, sex, date of birth, race and ethnicity are only in the label.
{
"type": "Person",
"countries": [{ "country": "us" }],
"customFormat": "{lastName}, {firstName} {middleName} | {sex} | DOB {dob} | {race} / {ethnicity}",
"lastNameCaseOutput": "Upper",
"sexOutputFormat": "Abbreviated",
"dobMean": "1975-06-01",
"dobStdDev": 5475,
"dobStart": "1930-01-01",
"dobEnd": "2006-12-31",
"seed": 2,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"custom": { "column": "label", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name | label |
|---|---|---|
| Gustave | MARSDEN | MARSDEN, Gustave Franciszek | M | DOB 1963-10-21 | White / Hispanic |
| Haskel | MORAITIS | MORAITIS, Haskel Cyrille | M | DOB 1987-05-14 | White / NonHispanic |
| Maryem | JAYJOHN | JAYJOHN, Maryem Gormley | F | DOB 1995-06-07 | White / NonHispanic |
| Yarisel | BINNEY | BINNEY, Yarisel Maisy | F | DOB 1978-12-15 | TwoOrMoreRaces / NonHispanic |
| Lucelia | SLESSER | SLESSER, Lucelia Llagas | F | DOB 1977-01-30 | White / NonHispanic |
| Sheriff | ZOSEL | ZOSEL, Sheriff Vandriessche | M | DOB 1977-07-10 | White / NonHispanic |
Each value in the label is the value the sub-field has as a column. lastNameCaseOutput applies to the
last name in both last_name and the label, and sexOutputFormat applies to the sex in the label.
A JSON value
{{ and }} write a literal brace, so a template can produce JSON. The braces around the JSON object
are written as {{ and }}, and each {name} inside them is replaced with the row's value.
{
"type": "Person",
"countries": [
{ "country": "gb", "weight": 2 },
{ "country": "fr" }
],
"customFormat": "{{\"name\": \"{firstName} {lastName}\", \"born\": \"{dob}\", \"sex\": \"{sex}\"}}",
"dobStart": "1950-01-01",
"dobEnd": "2000-12-31",
"seed": 1,
"map": {
"custom": { "column": "profile", "dataType": "VarChar" }
}
}
Sample output:
| profile |
|---|
| {"name": "Chhavi Kompus", "born": "1975-05-14", "sex": "Female"} |
| {"name": "Jeanne-Hélène Woo", "born": "1984-04-08", "sex": "Female"} |
| {"name": "Lunah Narraway", "born": "1977-07-25", "sex": "Female"} |
| {"name": "Riga Lavigne", "born": "1955-08-11", "sex": "Female"} |
| {"name": "Gulcan Meziri", "born": "1988-12-19", "sex": "Female"} |
A staff code from initials
The first initial, the first three letters of the last name, and five random digits. pad fills a last
name shorter than three letters, so every code has the same length.
{
"type": "Person",
"countries": [{ "country": "us" }],
"derivedId": [
{ "source": "FirstName", "length": 1, "case": "Upper" },
{ "source": "LastName", "length": 3, "case": "Upper", "pad": "X" },
"-",
{ "source": "Number", "length": 5 }
],
"seed": 57,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"derivedId": { "column": "staff_code", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name | staff_code |
|---|---|---|
| Greyson | Eh | GEHX-93400 |
| Tajuanna | Marynowski | TMAR-22981 |
| Yoshimi | Swanger | YSWA-86832 |
| Takelia | Karos | TKAR-33869 |
| Adalberta | Ihasz | AIHA-21902 |
| Bathsheba | Hatley | BHAT-92424 |
Eh has two letters, so pad adds an X to make EHX.
A UK driving license number
This identifier follows the layout of a UK driving license number, sixteen characters: five letters of the last name, the decade digit of the year of birth, the month of birth with 50 added for a female person, the day of birth, the last digit of the year of birth, the first and middle initials, two random digits and a Luhn check digit.
{
"type": "Person",
"countries": [{ "country": "gb" }],
"dobStart": "1960-01-01",
"dobEnd": "2005-12-31",
"middleNamePercentageFirstName": 100,
"derivedId": [
{ "source": "LastName", "length": 5, "pad": "9", "case": "Upper" },
{ "source": "Dob", "part": "Year", "start": 3, "length": 1 },
{ "source": "Dob", "part": "Month", "addWhenFemale": 50, "length": 2 },
{ "source": "Dob", "part": "Day", "length": 2 },
{ "source": "Dob", "part": "Year", "length": 1 },
{ "source": "FirstName", "length": 1, "case": "Upper" },
{ "source": "MiddleName", "length": 1, "case": "Upper" },
{ "source": "Number", "length": 2 },
{ "source": "Checksum", "method": "Luhn" }
],
"seed": 2,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"dob": { "column": "date_of_birth", "dataType": "Date" },
"sex": { "column": "sex", "dataType": "VarChar" },
"derivedId": { "column": "license_number", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name | date_of_birth | sex | license_number |
|---|---|---|---|---|
| Addy | Bolat | 1990-05-22 | Male | BOLAT905220AB372 |
| Yanet | McBurney | 1968-11-25 | Female | MCBUR661258YE699 |
| Sophie-Louise | Landles | 1984-05-14 | Female | LANDL855144SA242 |
| Sughra | Satterly | 1990-09-13 | Female | SATTE959130SL469 |
| Merin | Igwe | 1998-10-15 | Female | IGWE9960158MZ047 |
In the first row, 9 after BOLAT is the decade digit of 1990 and 0 after the day is its last digit. The second row is female, so November is written as 61. Igwe has four letters, so pad adds a 9 to make IGWE9.
A license number with a phonetic code
The first letter of the last name, then three digits of the last name's Soundex code, three digits of the first name's Soundex code, and the date of birth with 50 added to the month for a female person.
{
"type": "Person",
"countries": [{ "country": "us" }],
"dobStart": "1960-01-01",
"dobEnd": "2005-12-31",
"derivedId": [
{ "source": "LastName", "length": 1, "case": "Upper" },
{ "source": "LastName", "phonetic": "Soundex", "start": 2, "length": 3 },
{ "source": "FirstName", "phonetic": "Soundex", "start": 2, "length": 3 },
{ "source": "Dob", "part": "Year", "length": 2 },
{ "source": "Dob", "part": "Month", "addWhenFemale": 50, "length": 2 },
{ "source": "Dob", "part": "Day", "length": 2 },
{ "source": "Number", "length": 1 }
],
"seed": 9,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"derivedId": { "column": "license_number", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name | license_number |
|---|---|---|
| Markiya | Hospodar | H2136206551115 |
| Rogers | Meres | M6202628907195 |
| Jacquelin | Haspel | H2142459753052 |
| Marqui | Asi | A2006206205044 |
| Geremiah | Argaw | A6206508811049 |
In the first row, Hospodar has the Soundex code H213 and Markiya has M620, so the number starts with H213620. The next digits are the year 65, the month 51, which is January with 50 added for a female person, and the day 11.
A member number with a check digit
A Verhoeff check digit lets a system that reads the member number detect a mistyped number.
{
"type": "Person",
"countries": [{ "country": "us" }],
"dobStart": "1950-01-01",
"dobEnd": "2006-12-31",
"derivedId": [
"MB-",
{ "source": "Dob", "part": "Year", "length": 2 },
{ "source": "Number", "length": 6 },
"-",
{ "source": "Checksum", "method": "Verhoeff" }
],
"seed": 1,
"map": { "derivedId": { "column": "member_number", "dataType": "VarChar" } }
}
Sample output:
| member_number |
|---|
| MB-91764391-9 |
| MB-72396626-3 |
| MB-84717388-5 |
| MB-96529634-1 |
| MB-92235136-2 |
The final digit is calculated from the eight digits before it. A wrong digit, or two adjacent digits swapped, produces a number that fails the check.
An email address that matches the person
The email address is built from the row's own first name and last name, so it matches the first_name
and last_name columns. sanitize removes accents, apostrophes and hyphens, which the local part of an
email address cannot contain.
{
"type": "Person",
"countries": [
{ "country": "pt", "weight": 2 },
{ "country": "no" },
{ "country": "ie" },
{ "country": "pl" },
{ "country": "de" }
],
"derivedId": [
{ "source": "FirstName", "sanitize": "Letters", "case": "Lower" },
".",
{ "source": "LastName", "sanitize": "Letters", "case": "Lower" },
{ "source": "Number", "length": 2 },
{
"source": "Lookup",
"lookupValues": [
{ "value": "@example.com", "weight": 6 },
{ "value": "@example.net", "weight": 3 },
{ "value": "@example.org", "weight": 1 }
]
}
],
"seed": 19,
"map": {
"firstName": { "column": "first_name", "dataType": "VarChar" },
"lastName": { "column": "last_name", "dataType": "VarChar" },
"derivedId": { "column": "email", "dataType": "VarChar" }
}
}
Sample output:
| first_name | last_name | |
|---|---|---|
| Aleida | Barnabé | aleida.barnabe52@example.net |
| Jass | Martins Ferreira | jass.martinsferreira57@example.com |
| Claudia | Ottesen | claudia.ottesen47@example.com |
| Inocencio | Martins Da Silva | inocencio.martinsdasilva24@example.org |
| Sali | Stolarski | sali.stolarski42@example.com |
| Helena Isabel | Lopes Ribeiro | helenaisabel.lopesribeiro73@example.com |
é in Barnabé is e, and the spaces in Martins Ferreira, Martins Da Silva, Helena Isabel and Lopes Ribeiro are removed. The name columns are not changed, because sanitize applies only to the section.
The two random digits make two people with the same name less likely to have the same address. The
domain is a weighted Lookup section. Set unique to reject any row with an address that is already
used.
An email address not linked to a person
For an email address that does not need to match a name in the row, use
Identifier.