0
# String Parsing
1
2
Safe string parsing methods that return `Option` types instead of throwing exceptions, providing a more functional approach to string-to-number conversions.
3
4
## StringOps Extension Methods
5
6
```scala { .api }
7
implicit class StringOps(s: String) {
8
def toBooleanOption: Option[Boolean]
9
def toByteOption: Option[Byte]
10
def toShortOption: Option[Short]
11
def toIntOption: Option[Int]
12
def toLongOption: Option[Long]
13
def toFloatOption: Option[Float]
14
def toDoubleOption: Option[Double]
15
}
16
```
17
18
All methods return `Option` types and handle parsing failures gracefully by returning `None` instead of throwing exceptions.
19
20
## Method Details
21
22
### toBooleanOption
23
24
```scala { .api }
25
def toBooleanOption: Option[Boolean]
26
```
27
28
Attempts to parse the string as a `Boolean`.
29
30
**Returns:**
31
- `Some(true)` if the string is "true" (case insensitive)
32
- `Some(false)` if the string is "false" (case insensitive)
33
- `None` for any other value
34
35
**Throws:**
36
- `NullPointerException` if the string is `null`
37
38
**Usage:**
39
```scala
40
"true".toBooleanOption // Some(true)
41
"TRUE".toBooleanOption // Some(true)
42
"false".toBooleanOption // Some(false)
43
"False".toBooleanOption // Some(false)
44
"yes".toBooleanOption // None
45
"1".toBooleanOption // None
46
```
47
48
### toByteOption
49
50
```scala { .api }
51
def toByteOption: Option[Byte]
52
```
53
54
Attempts to parse the string as a `Byte` (range: -128 to 127).
55
56
**Returns:**
57
- `Some(value)` if the string contains a valid byte value
58
- `None` if parsing fails or the value is out of range
59
60
**Throws:**
61
- `NullPointerException` if the string is `null`
62
63
**Usage:**
64
```scala
65
"42".toByteOption // Some(42)
66
"127".toByteOption // Some(127)
67
"-128".toByteOption // Some(-128)
68
"128".toByteOption // None (out of range)
69
"abc".toByteOption // None
70
```
71
72
### toShortOption
73
74
```scala { .api }
75
def toShortOption: Option[Short]
76
```
77
78
Attempts to parse the string as a `Short` (range: -32,768 to 32,767).
79
80
**Returns:**
81
- `Some(value)` if the string contains a valid short value
82
- `None` if parsing fails or the value is out of range
83
84
**Throws:**
85
- `NullPointerException` if the string is `null`
86
87
**Usage:**
88
```scala
89
"1000".toShortOption // Some(1000)
90
"32767".toShortOption // Some(32767)
91
"-32768".toShortOption // Some(-32768)
92
"40000".toShortOption // None (out of range)
93
"text".toShortOption // None
94
```
95
96
### toIntOption
97
98
```scala { .api }
99
def toIntOption: Option[Int]
100
```
101
102
Attempts to parse the string as an `Int`.
103
104
**Returns:**
105
- `Some(value)` if the string contains a valid integer value
106
- `None` if parsing fails
107
108
**Throws:**
109
- `NullPointerException` if the string is `null`
110
111
**Usage:**
112
```scala
113
"42".toIntOption // Some(42)
114
"-123".toIntOption // Some(-123)
115
"2147483647".toIntOption // Some(2147483647)
116
"3.14".toIntOption // None
117
"hello".toIntOption // None
118
```
119
120
### toLongOption
121
122
```scala { .api }
123
def toLongOption: Option[Long]
124
```
125
126
Attempts to parse the string as a `Long`.
127
128
**Returns:**
129
- `Some(value)` if the string contains a valid long value
130
- `None` if parsing fails
131
132
**Throws:**
133
- `NullPointerException` if the string is `null`
134
135
**Usage:**
136
```scala
137
"1234567890".toLongOption // Some(1234567890L)
138
"9223372036854775807".toLongOption // Some(9223372036854775807L)
139
"-9223372036854775808".toLongOption // Some(-9223372036854775808L)
140
"not_a_number".toLongOption // None
141
```
142
143
### toFloatOption
144
145
```scala { .api }
146
def toFloatOption: Option[Float]
147
```
148
149
Attempts to parse the string as a `Float`.
150
151
**Returns:**
152
- `Some(value)` if the string is a parsable `Float`
153
- `None` if parsing fails
154
155
**Throws:**
156
- `NullPointerException` if the string is `null`
157
158
**Usage:**
159
```scala
160
"3.14".toFloatOption // Some(3.14f)
161
"-42.5".toFloatOption // Some(-42.5f)
162
"1e10".toFloatOption // Some(1.0E10f)
163
"Infinity".toFloatOption // Some(Float.PositiveInfinity)
164
"invalid".toFloatOption // None
165
```
166
167
### toDoubleOption
168
169
```scala { .api }
170
def toDoubleOption: Option[Double]
171
```
172
173
Attempts to parse the string as a `Double`.
174
175
**Returns:**
176
- `Some(value)` if the string is a parsable `Double`
177
- `None` if parsing fails
178
179
**Throws:**
180
- `NullPointerException` if the string is `null`
181
182
**Usage:**
183
```scala
184
"3.14159".toDoubleOption // Some(3.14159)
185
"-42.5".toDoubleOption // Some(-42.5)
186
"1.23e-4".toDoubleOption // Some(1.23E-4)
187
"NaN".toDoubleOption // Some(Double.NaN)
188
"invalid".toDoubleOption // None
189
```
190
191
## Complete Usage Example
192
193
```scala
194
import scala.collection.compat._
195
196
def parseUserInput(input: String): Either[String, Double] = {
197
input.toDoubleOption match {
198
case Some(value) => Right(value)
199
case None => Left(s"Invalid number: $input")
200
}
201
}
202
203
// Safe configuration parsing
204
def parseConfig(config: Map[String, String]): Option[AppSettings] = {
205
for {
206
port <- config.get("port").flatMap(_.toIntOption)
207
timeout <- config.get("timeout").flatMap(_.toLongOption)
208
enabled <- config.get("enabled").flatMap(_.toBooleanOption)
209
} yield AppSettings(port, timeout, enabled)
210
}
211
212
// Safe arithmetic
213
def divide(a: String, b: String): Option[Double] = {
214
for {
215
num1 <- a.toDoubleOption
216
num2 <- b.toDoubleOption
217
if num2 != 0.0
218
} yield num1 / num2
219
}
220
```
221
222
## Migration from Exception-Based Parsing
223
224
**Before (throws exceptions):**
225
```scala
226
try {
227
val value = "42".toInt
228
// handle value
229
} catch {
230
case _: NumberFormatException => // handle error
231
}
232
```
233
234
**After (with Option):**
235
```scala
236
"42".toIntOption match {
237
case Some(value) => // handle value
238
case None => // handle error
239
}
240
```
241
242
## Implementation Notes
243
244
- All parsing methods are null-safe but will throw `NullPointerException` for `null` input
245
- Methods handle edge cases like "Infinity", "NaN" for floating-point types
246
- Implementation delegates to the standard library parsing methods but catches exceptions
247
- These methods are backports of Scala 2.13 functionality for earlier versions